From 8f4873fa4e467593e4685bf25683d2149e9a8419 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 19 Jul 2017 19:37:18 +0300 Subject: [PATCH 001/336] =?UTF-8?q?=D0=9F=D0=BE=D1=84=D0=B8=D0=BA=D1=88?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BA=D0=BE=D0=BD=D0=BD=D0=B5=D0=BA=D1=82=20?= =?UTF-8?q?=D0=BF=D0=BE=20Bluetooth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/trackPlatform.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index cf94e21..30bea26 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -38,6 +38,6 @@ void loop() if (command[0] == servoControllerID) { servoController.exec(device, command); } else { - controller.handle(device, device->read()); + controller.handle(device, command); } } From e7a77b6134f8f007fd37c248b2bda802618e6ea8 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 22 Jul 2017 19:40:02 +0300 Subject: [PATCH 002/336] =?UTF-8?q?*=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BF=D0=B8=D0=BD=D1=8B=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B8?= =?UTF-8?q?=20wifi,=20=D0=B3=D1=83=D1=81=D0=B5=D0=BD=D0=B8=D1=86=20=D0=B8?= =?UTF-8?q?=20=D1=81=D0=B5=D1=80=D0=B2=D0=BE=D0=BF=D1=80=D0=B8=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=D0=BE=D0=B2=20(=D0=B8=D0=B7-=D0=B7=D0=B0=20=D0=BE=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20arduin?= =?UTF-8?q?o=20=D0=BD=D0=B0=20SoftwareSerial).=20*=20=D0=9A=D0=BE=D0=BD?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BD=D1=82=D1=8B=20=D1=82=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C=20=D0=B4=D0=B5=D0=B9=D1=81=D1=82=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=20=D1=81=D1=82=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20*=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BE=D0=BF=D0=B5=D1=87=D0=B0=D1=82=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B2=20Readme=20*=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=B8=D0=B7=20=D0=BA=D0=BE=D0=B4=D0=B0=20=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82=20=D0=B2=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=BE=20=D1=81=D0=B0=D0=BC=D0=B8=D1=85=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- code/Arduino/Constants.cpp | 59 +++++++++++++------------- code/Arduino/Constants.h | 66 +++++++++++++++--------------- code/Arduino/MainController.cpp | 2 +- code/Arduino/SensorsController.cpp | 5 +-- 5 files changed, 67 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 9d4f767..2647d09 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ - Драйвер двигателя (L298N) - Поворотная платформа -Датчики расстояния объедены в модуль, который несложно снимается, что позволяет заменить датчики. В модуле 5 датчиков расстояния, расположенных под различными углами для улучшения ориентирования на местности. Так же углы поворота датчиков можно настраивать в небольшом диапазоне. Расположены спереди платформы. +Датчики расстояния объеденены в модуль, который несложно снимается, что позволяет заменить датчики. В модуле 5 датчиков расстояния, расположенных под различными углами для улучшения ориентирования на местности. Так же углы поворота датчиков можно настраивать в небольшом диапазоне. Расположены спереди платформы. ![](https://pp.userapi.com/c626121/v626121114/60cc7/xe6EOab8Ysw.jpg) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 01c2e46..10a3488 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -1,36 +1,37 @@ #include "Constants.h" +const uint8_t Constants::bluetooth_RX = 50; +const uint8_t Constants::bluetooth_TX = 51; +const uint32_t Constants::bluetooth_serial_speed = 9600; + +const uint8_t Constants::wifi_RX = 10; +const uint8_t Constants::wifi_TX = 11; +const uint32_t Constants::wifi_serial_speed = 9600; + +const uint8_t Constants::left_engine_enable = 29; +const uint8_t Constants::left_engine_straight_pin = 30; +const uint8_t Constants::left_engine_reverse_pin = 31; +const uint8_t Constants::right_engine_straight_pin = 32; +const uint8_t Constants::right_engine_reverse_pin = 33; +const uint8_t Constants::right_engine_enable = 34; + +const uint8_t Constants::distance_sensor_read_pin = A0; +const uint8_t Constants::distance_sensor_a_pin = 4; +const uint8_t Constants::distance_sensor_b_pin = 5; +const uint8_t Constants::distance_sensor_c_pin = 6; + +const uint8_t Constants::line_sensor_read_pin = A1; +const uint8_t Constants::line_sensor_a_pin = 15; +const uint8_t Constants::line_sensor_b_pin = 16; +const uint8_t Constants::line_sensor_c_pin = 17; + +const uint8_t Constants::servo_horizontal_pin = 38; +const uint8_t Constants::servo_vertical_pin = 39; + +const char Constants::commands_delimetr = ';'; + Constants::Constants() { - bluetooth_RX = 50; - bluetooth_TX = 51; - bluetooth_serial_speed = 9600; - - wifi_RX = 30; - wifi_TX = 31; - wifi_serial_speed = 9600; - - left_engine_enable = 7; - left_engine_straight_pin = 8; - left_engine_reverse_pin = 9; - right_engine_straight_pin = 10; - right_engine_reverse_pin = 11; - right_engine_enable = 12; - - /*distance_sensor_read_pin = A0;*/ - distance_sensor_a_pin = 4; - distance_sensor_b_pin = 5; - distance_sensor_c_pin = 6; - - //line_sensor_read_pin = A1; - line_sensor_a_pin = 15; - line_sensor_b_pin = 16; - line_sensor_c_pin = 17; - - servo_horizontal_pin = 34; - servo_vertical_pin = 35; - - commands_delimetr = ';'; } diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index 7bc6e8c..c261a29 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -1,40 +1,40 @@ -#pragma once -#include +#pragma once +#include class Constants { public: - int bluetooth_RX; - int bluetooth_TX; - int bluetooth_serial_speed; - - int wifi_RX; - int wifi_TX; - int wifi_serial_speed; - - int left_engine_straight_pin; - int left_engine_reverse_pin; - int right_engine_straight_pin; - int right_engine_reverse_pin; - - int left_engine_enable; - int right_engine_enable; - - long distance_sensor_read_pin; - int distance_sensor_a_pin; - int distance_sensor_b_pin; - int distance_sensor_c_pin; - - - long line_sensor_read_pin; - int line_sensor_a_pin; - int line_sensor_b_pin; - int line_sensor_c_pin; - - int servo_horizontal_pin; - int servo_vertical_pin; - - char commands_delimetr; + static const uint8_t bluetooth_RX; + static const uint8_t bluetooth_TX; + static const uint32_t bluetooth_serial_speed; + + static const uint8_t wifi_RX; + static const uint8_t wifi_TX; + static const uint32_t wifi_serial_speed; + + static const uint8_t left_engine_straight_pin; + static const uint8_t left_engine_reverse_pin; + static const uint8_t right_engine_straight_pin; + static const uint8_t right_engine_reverse_pin; + + static const uint8_t left_engine_enable; + static const uint8_t right_engine_enable; + + static const uint8_t distance_sensor_read_pin; + static const uint8_t distance_sensor_a_pin; + static const uint8_t distance_sensor_b_pin; + static const uint8_t distance_sensor_c_pin; + + + static const uint8_t line_sensor_read_pin; + static const uint8_t line_sensor_a_pin; + static const uint8_t line_sensor_b_pin; + static const uint8_t line_sensor_c_pin; + + static const uint8_t servo_horizontal_pin; + static const uint8_t servo_vertical_pin; + + static const char commands_delimetr; Constants(); ~Constants(); diff --git a/code/Arduino/MainController.cpp b/code/Arduino/MainController.cpp index 15f4a5e..1988ff9 100644 --- a/code/Arduino/MainController.cpp +++ b/code/Arduino/MainController.cpp @@ -28,7 +28,7 @@ String MainController::intArrayToString(int* array, int size) { String str = ""; for (int i = 0; i < size; i++) { str += String(array[i]); - str += ";"; + str += constants.commands_delimetr; } return str; } diff --git a/code/Arduino/SensorsController.cpp b/code/Arduino/SensorsController.cpp index 2004874..a857824 100644 --- a/code/Arduino/SensorsController.cpp +++ b/code/Arduino/SensorsController.cpp @@ -1,7 +1,6 @@ #include "SensorsController.h" - SensorsController::SensorsController() { countDistanceSensors = 5; @@ -76,7 +75,7 @@ void SensorsController::chooseLineSensor(int number) { int SensorsController::getLine(int number) { chooseLineSensor(number); - return analogRead(A1) > minimalLineBound ? 1 : 0; + return analogRead(constants.line_sensor_read_pin) > minimalLineBound ? 1 : 0; } int* SensorsController::getLineAll() { @@ -122,7 +121,7 @@ void SensorsController::chooseDistanceSensor(int number) { int SensorsController::getDistance(int number) { chooseDistanceSensor(number); - float volts = analogRead(A0); + float volts = analogRead(constants.distance_sensor_read_pin); float distance = (6762 / (volts)) - 4; return distance; } From 9220e18bc38862240c63b04996539af2149b4f1b Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 24 Jul 2017 11:20:41 +0300 Subject: [PATCH 003/336] C++ API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Добавлены API перемещения робота Arduino * Константы вынесены в общий файл (из классов) --- code/Arduino/CommandsEnum.h | 12 ++- code/Arduino/ConnectingDevice.cpp | 1 + code/Arduino/Constants.cpp | 8 ++ code/Arduino/Constants.h | 9 ++ code/Arduino/MovementController.cpp | 4 +- code/Arduino/ServoController.cpp | 8 +- code/c++/cxx-api/CommandsEnum.h | 47 ++++++++++ .../cxx-api/TrackPlatform_BasicConnector.cpp | 6 ++ .../cxx-api/TrackPlatform_BasicConnector.h | 21 +++++ .../cxx-api/TrackPlatform_BasicManagement.cpp | 92 +++++++++++++++++++ .../cxx-api/TrackPlatform_BasicManagement.h | 39 ++++++++ code/c++/cxx-api/cxx-api.sln | 28 ++++++ .../cxx-api.vcxproj} | 55 +++++------ code/c++/cxx-api/cxx-api.vcxproj.filters | 36 ++++++++ code/c++/trackPlatform/trackPlatform.sln | 28 ------ .../trackPlatform/trackPlatform/ComPort.cpp | 92 ------------------- .../c++/trackPlatform/trackPlatform/ComPort.h | 33 ------- .../trackPlatform/trackPlatform/Commands.cpp | 12 --- .../trackPlatform/trackPlatform/Commands.h | 8 -- code/c++/trackPlatform/trackPlatform/Menu.cpp | 27 ------ code/c++/trackPlatform/trackPlatform/Menu.h | 13 --- code/c++/trackPlatform/trackPlatform/main.cpp | 42 --------- .../trackPlatform.vcxproj.filters | 42 --------- 23 files changed, 321 insertions(+), 342 deletions(-) create mode 100644 code/c++/cxx-api/CommandsEnum.h create mode 100644 code/c++/cxx-api/TrackPlatform_BasicConnector.cpp create mode 100644 code/c++/cxx-api/TrackPlatform_BasicConnector.h create mode 100644 code/c++/cxx-api/TrackPlatform_BasicManagement.cpp create mode 100644 code/c++/cxx-api/TrackPlatform_BasicManagement.h create mode 100644 code/c++/cxx-api/cxx-api.sln rename code/c++/{trackPlatform/trackPlatform/trackPlatform.vcxproj => cxx-api/cxx-api.vcxproj} (75%) create mode 100644 code/c++/cxx-api/cxx-api.vcxproj.filters delete mode 100644 code/c++/trackPlatform/trackPlatform.sln delete mode 100644 code/c++/trackPlatform/trackPlatform/ComPort.cpp delete mode 100644 code/c++/trackPlatform/trackPlatform/ComPort.h delete mode 100644 code/c++/trackPlatform/trackPlatform/Commands.cpp delete mode 100644 code/c++/trackPlatform/trackPlatform/Commands.h delete mode 100644 code/c++/trackPlatform/trackPlatform/Menu.cpp delete mode 100644 code/c++/trackPlatform/trackPlatform/Menu.h delete mode 100644 code/c++/trackPlatform/trackPlatform/main.cpp delete mode 100644 code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj.filters diff --git a/code/Arduino/CommandsEnum.h b/code/Arduino/CommandsEnum.h index 4797d95..f5501c8 100644 --- a/code/Arduino/CommandsEnum.h +++ b/code/Arduino/CommandsEnum.h @@ -1,8 +1,8 @@ -#pragma once - +#ifndef _COMMANDS_ENUM_H_ +#define _COMMANDS_ENUM_H_ enum ControllerEnum { - movementControllerID = '\001', + movementControllerID = '\001', sensorsControllerID = '\002', servoControllerID = '\003' }; @@ -17,7 +17,7 @@ enum SensorsEnum { enum MoveEnum { forward = '\001', //move forward - left = '\002', //move left + left = '\002', //move left right = '\003', //move right back = '\004', //move back stop = '\005', //stop @@ -42,4 +42,6 @@ enum ServoCommands { set_vertical_angle = '\002', //set vertical angle of servo set_horiz_vertical_angles = '\003', //set horizontal and verticalse angles of servo get_coodrinates = '\004', //get current angels of horizontal and vertical servos -}; \ No newline at end of file +}; + +#endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/Arduino/ConnectingDevice.cpp b/code/Arduino/ConnectingDevice.cpp index e52db5f..a87fa4b 100644 --- a/code/Arduino/ConnectingDevice.cpp +++ b/code/Arduino/ConnectingDevice.cpp @@ -35,4 +35,5 @@ String ConnectingDevice::read() ConnectingDevice::~ConnectingDevice() { + delete device; } diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 10a3488..e69567f 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -30,6 +30,14 @@ const uint8_t Constants::servo_vertical_pin = 39; const char Constants::commands_delimetr = ';'; +const uint8_t Constants::min_speed = 0; +const uint8_t Constants::max_speed = 255; +const uint8_t Constants::servo_delay = 200; + +const uint8_t Constants::countDistanceSensors = 5; +const uint8_t Constants::countLineSensors = 5; +const uint8_t Constants::minimalLineBound = 270; + Constants::Constants() { } diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index c261a29..237ff00 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -36,6 +36,15 @@ class Constants static const char commands_delimetr; + /* Class constants */ + static const uint8_t min_speed; + static const uint8_t max_speed; + static const uint16_t servo_delay; + + static const uint16_t countDistanceSensors; + static const uint16_t countLineSensors; + static const uint16_t minimalLineBound; + Constants(); ~Constants(); }; diff --git a/code/Arduino/MovementController.cpp b/code/Arduino/MovementController.cpp index 62e9bb7..f6ba968 100644 --- a/code/Arduino/MovementController.cpp +++ b/code/Arduino/MovementController.cpp @@ -4,8 +4,8 @@ MovementController::MovementController() { - MIN_SPEED = 0; - MAX_SPEED = 255; + MIN_SPEED = constants.min_speed; + MAX_SPEED = constants.max_speed; pinMode(constants.left_engine_enable, OUTPUT); pinMode(constants.left_engine_straight_pin, OUTPUT); diff --git a/code/Arduino/ServoController.cpp b/code/Arduino/ServoController.cpp index 3f5ab65..e249437 100644 --- a/code/Arduino/ServoController.cpp +++ b/code/Arduino/ServoController.cpp @@ -36,18 +36,18 @@ void ServoController::exec(ConnectingDevice* device, String command) { void ServoController::setHorizontalAngle(int angle) { horizontalServo.write(angle); - delay(20); + delay(constants.servo_delay); } void ServoController::setVerticalAngle(int angle) { verticalServo.write(angle); - delay(20); + delay(constants.servo_delay); } void ServoController::setHorizontalAndVerticalAngle(int angleX, int angleY) { horizontalServo.write(angleX); verticalServo.write(angleY); - delay(20); + delay(constants.servo_delay); } int* ServoController::getCoordinates() { @@ -60,7 +60,7 @@ int* ServoController::getCoordinates() { void ServoController::setHorizontalAndVerticalAngle(int* arr) { horizontalServo.write(arr[0]); verticalServo.write(arr[1]); - delay(200); + delay(constants.servo_delay); } int ServoController::getHorizontalAngel() { diff --git a/code/c++/cxx-api/CommandsEnum.h b/code/c++/cxx-api/CommandsEnum.h new file mode 100644 index 0000000..f5501c8 --- /dev/null +++ b/code/c++/cxx-api/CommandsEnum.h @@ -0,0 +1,47 @@ +#ifndef _COMMANDS_ENUM_H_ +#define _COMMANDS_ENUM_H_ + +enum ControllerEnum { + movementControllerID = '\001', + sensorsControllerID = '\002', + servoControllerID = '\003' +}; + +enum SensorsEnum { + distance_sensor = '\001', //get value from single distance senceor + distance_sensor_all = '\002', //get value from all distance senceors + line_sensor = '\003', //get value from single line senceor + line_sensor_all = '\004' //get value from all line senceors +}; + + +enum MoveEnum { + forward = '\001', //move forward + left = '\002', //move left + right = '\003', //move right + back = '\004', //move back + stop = '\005', //stop + forward_speed = '\006', //move forward with established speed + forward_time = '\007', //move forward while established time + back_speed = '\010', //move back with established speed + track_set_speed = '\011' //choose track and set passed speed +}; + +enum TrackDiraction { + forward_direction = true, //rotation of track in forward diration + back_direction = false //rotation of track in backword diration +}; + +enum TrackID { + left_track = 0, //left track id + right_track = 1 //right track id +}; + +enum ServoCommands { + set_horizontal_angle = '\001', //set horizontal angle of servo + set_vertical_angle = '\002', //set vertical angle of servo + set_horiz_vertical_angles = '\003', //set horizontal and verticalse angles of servo + get_coodrinates = '\004', //get current angels of horizontal and vertical servos +}; + +#endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp new file mode 100644 index 0000000..f0f74bf --- /dev/null +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -0,0 +1,6 @@ +#include "TrackPlatform_BasicConnector.h" + +TrackPlatform_BasicConnector::TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : + rxLocation(rx), txLocation(tx), baudRate(baudRate) +{ +} diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h new file mode 100644 index 0000000..3ae6218 --- /dev/null +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -0,0 +1,21 @@ +#ifndef _TRACKPLATFORM_BASICCONNECTOR_H_ +#define _TRACKPLATFORM_BASICCONNECTOR_H_ + +#include + +class TrackPlatform_BasicConnector +{ + std::string rxLocation; + std::string txLocation; + uint32_t baudRate; + +public: + TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); + virtual ~TrackPlatform_BasicConnector() = 0; + + virtual std::string read() = 0; + virtual void write(const std::string& s) = 0; + virtual bool isAvailable() = 0; +}; + +#endif /* _TRACKPLATFORM_BASICCONNECTOR_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp new file mode 100644 index 0000000..b2d6a12 --- /dev/null +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -0,0 +1,92 @@ +#include "TrackPlatform_BasicManagement.h" + +void TrackPlatform_BasicManagement::move(const std::string& additionalInfo) const +{ + connector->write(static_cast(movementControllerID) + additionalInfo); +} + +TrackPlatform_BasicManagement::TrackPlatform_BasicManagement(TrackPlatform_BasicConnector* connector) + : connector(connector) +{ +} + +void TrackPlatform_BasicManagement::moveForward() const +{ + std::string toSend(1, forward); + move(toSend); +} + +bool TrackPlatform_BasicManagement::moveForward(double speed) const +{ + if (speed < 0 || speed > 1) + { + return false; + } + + std::string toSend(1, forward_speed); + toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); + move(toSend); + + return true; +} + +void TrackPlatform_BasicManagement::moveForward(uint32_t timeInMSec) const +{ + std::string toSend(1, forward_time); + toSend += std::to_string(timeInMSec); + move(toSend); +} + +void TrackPlatform_BasicManagement::moveBackward() const +{ + std::string toSend(1, back); + move(toSend); +} + +bool TrackPlatform_BasicManagement::moveBackward(double speed) const +{ + if (speed < 0 || speed > 1) + { + return false; + } + + std::string toSend(1, back_speed); + toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); + move(toSend); + + return true; +} + +void TrackPlatform_BasicManagement::rotateClockwise() const +{ + std::string toSend(1, right); + move(toSend); +} + +void TrackPlatform_BasicManagement::rotateAntiClockwise() const +{ + std::string toSend(1, left); + move(toSend); +} + +void TrackPlatform_BasicManagement::moveStopAll() const +{ + std::string toSend(1, stop); + move(toSend); +} + +bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double speed) const +{ + if (speed < 0 || speed > 1) + { + return false; + } + + std::string toSend(1, back_speed); + toSend += std::to_string(*reinterpret_cast(&trackId)); + toSend += delimiter; + toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); + move(toSend); + + return true; +} diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h new file mode 100644 index 0000000..09409a4 --- /dev/null +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -0,0 +1,39 @@ +#ifndef _TRACKPLATFORM_BASICMANAGEMENT_H_ +#define _TRACKPLATFORM_BASICMANAGEMENT_H_ + +#include "TrackPlatform_BasicConnector.h" +#include "CommandsEnum.h" + +class TrackPlatform_BasicManagement +{ + TrackPlatform_BasicConnector* connector; + + static const uint8_t minSpeed = 0; + static const uint8_t maxSpeed = 255; + static const char delimiter = ';'; + +protected: + void move(const std::string& additionalInfo) const; + +public: + TrackPlatform_BasicManagement(TrackPlatform_BasicConnector* connector); + + void moveForward() const; + //speed must be in [0,1] range + bool moveForward(double speed) const; + void moveForward(uint32_t timeInMSec) const; + + void moveBackward() const; + //speed must be in [0,1] range + bool moveBackward(double speed) const; + + void rotateClockwise() const; + void rotateAntiClockwise() const; + + void moveStopAll() const; + + //speed must be in [0,1] range + bool setTrackForwardSpeed(TrackID trackId, double speed) const; +}; + +#endif /* _TRACKPLATFORM_BASICMANAGEMENT_H_ */ diff --git a/code/c++/cxx-api/cxx-api.sln b/code/c++/cxx-api/cxx-api.sln new file mode 100644 index 0000000..2012296 --- /dev/null +++ b/code/c++/cxx-api/cxx-api.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-api", "cxx-api.vcxproj", "{32D3778A-E59E-4DBC-8D86-BD23B708CA12}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x64.ActiveCfg = Debug|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x64.Build.0 = Debug|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x86.ActiveCfg = Debug|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x86.Build.0 = Debug|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.ActiveCfg = Release|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.Build.0 = Release|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.ActiveCfg = Release|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj similarity index 75% rename from code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj rename to code/c++/cxx-api/cxx-api.vcxproj index c5e576e..367f616 100644 --- a/code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -20,33 +20,33 @@ 15.0 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90} + {32D3778A-E59E-4DBC-8D86-BD23B708CA12} Win32Proj - trackPlatform + cxxapi 10.0.14393.0 - Application + StaticLibrary true v141 - MultiByte + Unicode - Application + StaticLibrary false v141 true Unicode - Application + StaticLibrary true v141 Unicode - Application + StaticLibrary false v141 true @@ -70,28 +70,17 @@ - - true - - - true - - - false - - - false - + Level3 Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - Console + Windows @@ -100,10 +89,10 @@ Level3 Disabled - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _DEBUG;_LIB;%(PreprocessorDefinitions) - Console + Windows @@ -114,10 +103,10 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - Console + Windows true true @@ -130,24 +119,22 @@ MaxSpeed true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + NDEBUG;_LIB;%(PreprocessorDefinitions) - Console + Windows true true - - - - + + + - - - + + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters new file mode 100644 index 0000000..5eafa57 --- /dev/null +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/code/c++/trackPlatform/trackPlatform.sln b/code/c++/trackPlatform/trackPlatform.sln deleted file mode 100644 index 04be704..0000000 --- a/code/c++/trackPlatform/trackPlatform.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "trackPlatform", "trackPlatform\trackPlatform.vcxproj", "{DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Debug|x64.ActiveCfg = Debug|x64 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Debug|x64.Build.0 = Debug|x64 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Debug|x86.ActiveCfg = Debug|Win32 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Debug|x86.Build.0 = Debug|Win32 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Release|x64.ActiveCfg = Release|x64 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Release|x64.Build.0 = Release|x64 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Release|x86.ActiveCfg = Release|Win32 - {DFA451D9-6F5A-4485-9CAD-27F7E3C32A90}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/code/c++/trackPlatform/trackPlatform/ComPort.cpp b/code/c++/trackPlatform/trackPlatform/ComPort.cpp deleted file mode 100644 index 811e8b4..0000000 --- a/code/c++/trackPlatform/trackPlatform/ComPort.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "ComPort.h" - - - -ComPort::ComPort() -{ - -} - - -DWORD WINAPI readProc(LPVOID p) { - while (true) { - if (ReadFile(hCom, pbuf, 1, &bytesRead, 0) && bytesRead > 0) { - printf("msg-%s-end %d\n", pbuf, bytesRead); - } - if (bytesRead>0) - { - WriteFile(hCom, pbuf++, 1, &bWritten, NULL); - counter++; - if (counter == 10) { - SetEvent(hEvent); - buf[counter] = '\0'; - counter = 0; - pbuf = buf; - } - } - } -} - - -VOID WINAPI ComPort::writeProc(PVOID* p) { - -} - - -bool ComPort::init(char* portName) { - this->portName = portName; - hCom = CreateFile(strcat("\\\\.\\", portName), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - - if (hCom == INVALID_HANDLE_VALUE) { - printf(" %s\n", portName); - return false; - } - - GetCommState(hCom, &dcb); - dcb.BaudRate = CBR_9600; - dcb.ByteSize = 8; - dcb.Parity = NOPARITY; - dcb.StopBits = ONESTOPBIT; - fSuccess = SetCommState(hCom, &dcb); - - if (!fSuccess) { - printf(" SetCommState !\n"); - return false; - } - printf("%s \n", portName); - GetCommState(hCom, &dcb); - printf(" %s %d\n", portName, dcb.BaudRate); - - return true; -} - -void ComPort::send() { - -} - -string ComPort::read() { - -} - -void ComPort::createReadThread() { - readThread = CreateThread(NULL, 0, readProc,54 - &dwParam, 0, &dwThreadReadId); -} - -void ComPort::createWriteThread() { - writeThread = CreateThread(NULL, 0, writeProc, - &dwParam, 0, &dwThreadWriteId); -} - -void ComPort::initThreads() { - this->createReadThread(); - this->createWriteThread(); -} - -void ComPort::closePort() { - CloseHandle(hCom); -} - -ComPort::~ComPort() -{ -} diff --git a/code/c++/trackPlatform/trackPlatform/ComPort.h b/code/c++/trackPlatform/trackPlatform/ComPort.h deleted file mode 100644 index 1599046..0000000 --- a/code/c++/trackPlatform/trackPlatform/ComPort.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -using namespace std; - -class ComPort -{ -private: - char* portName; - DCB dcb; - BOOL fSuccess; - HANDLE readThread; - HANDLE writeThread; - DWORD dwParam, dwThreadReadId, dwThreadWriteId; - -public: - HANDLE hCom; - ComPort(); - bool init(char* portName); - void send(); - string read(); - void createReadThread(); - void createWriteThread(); - void initThreads(); - //DWORD WINAPI readProc(LPVOID); - DWORD WINAPI writeProc(LPVOID); - void closePort(); - ~ComPort(); -}; - diff --git a/code/c++/trackPlatform/trackPlatform/Commands.cpp b/code/c++/trackPlatform/trackPlatform/Commands.cpp deleted file mode 100644 index 8dcee1a..0000000 --- a/code/c++/trackPlatform/trackPlatform/Commands.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "Commands.h" - - - -Commands::Commands() -{ -} - - -Commands::~Commands() -{ -} diff --git a/code/c++/trackPlatform/trackPlatform/Commands.h b/code/c++/trackPlatform/trackPlatform/Commands.h deleted file mode 100644 index 694a703..0000000 --- a/code/c++/trackPlatform/trackPlatform/Commands.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -class Commands -{ -public: - Commands(); - ~Commands(); -}; - diff --git a/code/c++/trackPlatform/trackPlatform/Menu.cpp b/code/c++/trackPlatform/trackPlatform/Menu.cpp deleted file mode 100644 index 5cf3bf6..0000000 --- a/code/c++/trackPlatform/trackPlatform/Menu.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "Menu.h" - - - -Menu::Menu() -{ -} - -void Menu::show() { - cout << "Menu:" << endl; - cout << "1 - Move forward" << endl; - cout << "2 - Turn left" << endl; - cout << "3 - Turn right" << endl; - cout << "4 - Move back" << endl; - cout << "0 - Exit" << endl; -} - -int Menu::choose() { - int chooseMenuItem; - cin >> chooseMenuItem; - return chooseMenuItem; -} - - -Menu::~Menu() -{ -} diff --git a/code/c++/trackPlatform/trackPlatform/Menu.h b/code/c++/trackPlatform/trackPlatform/Menu.h deleted file mode 100644 index 1878db9..0000000 --- a/code/c++/trackPlatform/trackPlatform/Menu.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -using namespace std; - -class Menu -{ -public: - Menu(); - void show(); - int choose(); - ~Menu(); -}; - diff --git a/code/c++/trackPlatform/trackPlatform/main.cpp b/code/c++/trackPlatform/trackPlatform/main.cpp deleted file mode 100644 index 1f6b9d7..0000000 --- a/code/c++/trackPlatform/trackPlatform/main.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include -#include "ComPort.h" -#include "Commands.h" -#include "Menu.h" -#include -#include -using namespace std; - -char buf[128]; -char* pbuf = buf; -int counter = 0; - -ComPort comPort; -HANDLE hEvent; -DWORD bytesRead, bWritten; - -HANDLE hThread; - - - -int main() { - setlocale(LC_ALL, "Russian"); - - char* portName; - cout << "Input port name: "; - cin >> portName; - - if (!comPort.init(portName)) { - return 0; - } - - comPort.initThreads(); - - hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - - comPort.closePort(); - return 0; -} \ No newline at end of file diff --git a/code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj.filters b/code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj.filters deleted file mode 100644 index 4829d1d..0000000 --- a/code/c++/trackPlatform/trackPlatform/trackPlatform.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Файлы исходного кода - - - Файлы исходного кода - - - Файлы исходного кода - - - Файлы ресурсов - - - - - Заголовочные файлы - - - Заголовочные файлы - - - Заголовочные файлы - - - \ No newline at end of file From 30009598ae9dd10d868289d4487ef1b4b1e91131 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 24 Jul 2017 16:40:39 +0300 Subject: [PATCH 004/336] =?UTF-8?q?*=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20HC-05=20(06)=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D1=83=D0=BB=D0=B5=D0=B9=20Bluetooth=20(=D0=B2=20API)=20*?= =?UTF-8?q?=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=20=D0=BB=D0=B8=D1=88=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=BB?= =?UTF-8?q?=D0=B5=D1=80=20=D1=81=D0=B5=D1=80=D0=B2=D0=BE=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=D0=B0=20=D0=B4=D0=BB=D1=8F=20Arduino=20*=20?= =?UTF-8?q?=D0=9D=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=BE=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=BE=D0=B5=20readme=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 2 +- code/Arduino/SensorsController.cpp | 10 +- code/Arduino/ServoController.cpp | 2 +- code/Arduino/ServoController.h | 2 +- code/Arduino/trackPlatform.ino | 12 +- code/c++/cxx-api/BluetoothConnector.cpp | 30 + code/c++/cxx-api/BluetoothConnector.h | 22 + code/c++/cxx-api/ConnectionModes.h | 9 + code/c++/cxx-api/README.md | 7 + .../cxx-api/TrackPlatform_BasicConnector.h | 3 +- .../cxx-api/TrackPlatform_BasicManagement.cpp | 120 +- .../cxx-api/TrackPlatform_BasicManagement.h | 26 +- code/c++/cxx-api/TrackPlatform_Manager.cpp | 34 + code/c++/cxx-api/TrackPlatform_Manager.h | 16 + code/c++/cxx-api/cxx-api.vcxproj | 24 +- code/c++/cxx-api/cxx-api.vcxproj.filters | 42 + .../serial_support/include/serial/impl/unix.h | 221 ++++ .../serial_support/include/serial/impl/win.h | 207 ++++ .../serial_support/include/serial/serial.h | 775 ++++++++++++ .../serial_support/include/serial/v8stdint.h | 57 + .../src/impl/list_ports/list_ports_linux.cc | 335 ++++++ .../src/impl/list_ports/list_ports_osx.cc | 286 +++++ .../src/impl/list_ports/list_ports_win.cc | 152 +++ .../cxx-api/serial_support/src/impl/unix.cc | 1063 +++++++++++++++++ .../cxx-api/serial_support/src/impl/win.cc | 640 ++++++++++ code/c++/cxx-api/serial_support/src/serial.cc | 414 +++++++ 26 files changed, 4485 insertions(+), 26 deletions(-) create mode 100644 code/c++/cxx-api/BluetoothConnector.cpp create mode 100644 code/c++/cxx-api/BluetoothConnector.h create mode 100644 code/c++/cxx-api/ConnectionModes.h create mode 100644 code/c++/cxx-api/README.md create mode 100644 code/c++/cxx-api/TrackPlatform_Manager.cpp create mode 100644 code/c++/cxx-api/TrackPlatform_Manager.h create mode 100644 code/c++/cxx-api/serial_support/include/serial/impl/unix.h create mode 100644 code/c++/cxx-api/serial_support/include/serial/impl/win.h create mode 100644 code/c++/cxx-api/serial_support/include/serial/serial.h create mode 100644 code/c++/cxx-api/serial_support/include/serial/v8stdint.h create mode 100644 code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc create mode 100644 code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc create mode 100644 code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc create mode 100644 code/c++/cxx-api/serial_support/src/impl/unix.cc create mode 100644 code/c++/cxx-api/serial_support/src/impl/win.cc create mode 100644 code/c++/cxx-api/serial_support/src/serial.cc diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index e69567f..5949c9e 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -32,7 +32,7 @@ const char Constants::commands_delimetr = ';'; const uint8_t Constants::min_speed = 0; const uint8_t Constants::max_speed = 255; -const uint8_t Constants::servo_delay = 200; +const uint8_t Constants::servo_delay = 20; const uint8_t Constants::countDistanceSensors = 5; const uint8_t Constants::countLineSensors = 5; diff --git a/code/Arduino/SensorsController.cpp b/code/Arduino/SensorsController.cpp index a857824..ceb400a 100644 --- a/code/Arduino/SensorsController.cpp +++ b/code/Arduino/SensorsController.cpp @@ -3,9 +3,9 @@ SensorsController::SensorsController() { - countDistanceSensors = 5; - countLineSensors = 5; - minimalLineBound = 270; + countDistanceSensors = constants.countDistanceSensors; + countLineSensors = constants.countLineSensors; + minimalLineBound = constants.minimalLineBound; pinMode(constants.line_sensor_a_pin, OUTPUT); pinMode(constants.line_sensor_b_pin, OUTPUT); @@ -122,6 +122,10 @@ void SensorsController::chooseDistanceSensor(int number) { int SensorsController::getDistance(int number) { chooseDistanceSensor(number); float volts = analogRead(constants.distance_sensor_read_pin); + if (volts == 0) + { + return -1; //TODO: crutch + } float distance = (6762 / (volts)) - 4; return distance; } diff --git a/code/Arduino/ServoController.cpp b/code/Arduino/ServoController.cpp index e249437..3259d23 100644 --- a/code/Arduino/ServoController.cpp +++ b/code/Arduino/ServoController.cpp @@ -4,7 +4,7 @@ ServoController::ServoController() { - + init(); } void ServoController::init() { diff --git a/code/Arduino/ServoController.h b/code/Arduino/ServoController.h index 6a3dbcf..b142ae1 100644 --- a/code/Arduino/ServoController.h +++ b/code/Arduino/ServoController.h @@ -10,10 +10,10 @@ class ServoController : public MainController Servo horizontalServo; Servo verticalServo; + void init(); public: Constants constants; ServoController(); - void init(); void exec(ConnectingDevice*, String); void setHorizontalAngle(int angle); void setVerticalAngle(int angle); diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 30bea26..88fae46 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -11,13 +11,13 @@ Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bl WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); ConnectingDevice *device; CommandsController controller; -ServoController servoController; +//ServoController servoController; bool connected = false; void setup() { - servoController.init(); + //servoController.init(); while (!connected) { if (bluetooth.isActive()) { @@ -35,9 +35,9 @@ void loop() { delay(100); //for sending commands from mobile String command = device->read(); - if (command[0] == servoControllerID) { - servoController.exec(device, command); - } else { + //if (command[0] == servoControllerID) { + // servoController.exec(device, command); + //} else { controller.handle(device, command); - } + //} } diff --git a/code/c++/cxx-api/BluetoothConnector.cpp b/code/c++/cxx-api/BluetoothConnector.cpp new file mode 100644 index 0000000..fd3105e --- /dev/null +++ b/code/c++/cxx-api/BluetoothConnector.cpp @@ -0,0 +1,30 @@ +#include "BluetoothConnector.h" + +BluetoothConnector::BluetoothConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) + : TrackPlatform_BasicConnector(rx, tx, baudRate), readPort(new serial::Serial(rx, baudRate)), writePort((rx == tx) ? readPort : new serial::Serial(tx, baudRate)) +{ +} + +BluetoothConnector::~BluetoothConnector() +{ + if (readPort != writePort) + { + delete writePort; + } + delete readPort; +} + +std::string BluetoothConnector::read() +{ + return readPort->read(messageMaxSize); +} + +void BluetoothConnector::write(const std::string& s) +{ + writePort->write(s); +} + +bool BluetoothConnector::isConnected() +{ + return (readPort->isOpen() && writePort->isOpen()); +} diff --git a/code/c++/cxx-api/BluetoothConnector.h b/code/c++/cxx-api/BluetoothConnector.h new file mode 100644 index 0000000..3b67d02 --- /dev/null +++ b/code/c++/cxx-api/BluetoothConnector.h @@ -0,0 +1,22 @@ +#ifndef _BLUETOOTH_CONNECTOR_H_ +#define _BLUETOOTH_CONNECTOR_H_ + +#include "TrackPlatform_BasicConnector.h" +#include "serial/serial.h" + +class BluetoothConnector : public TrackPlatform_BasicConnector +{ + static const size_t messageMaxSize = 65535; + + serial::Serial* readPort; + serial::Serial* writePort; + +public: + BluetoothConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); + ~BluetoothConnector() override; + std::string read() override; + void write(const std::string& s) override; + bool isConnected() override; +}; + +#endif /* _BLUETOOTH_CONNECTOR_H_ */ diff --git a/code/c++/cxx-api/ConnectionModes.h b/code/c++/cxx-api/ConnectionModes.h new file mode 100644 index 0000000..e6312d5 --- /dev/null +++ b/code/c++/cxx-api/ConnectionModes.h @@ -0,0 +1,9 @@ +#ifndef _CONNECTION_MODES_H_ +#define _CONNECTION_MODES_H_ + +enum ConnectionModes +{ + bluetooth +}; + +#endif /* _CONNECTION_MODES_H_ */ diff --git a/code/c++/cxx-api/README.md b/code/c++/cxx-api/README.md new file mode 100644 index 0000000..8cd3c67 --- /dev/null +++ b/code/c++/cxx-api/README.md @@ -0,0 +1,7 @@ +# trackPlatform C++ API + +API для платформы trackPlatrorm для языка C++. +Зависимости: +* https://github.com/wjwwood/serial - кросс-платформенная библиотека для использования последовательных портов (лежит в папке `serial_support`) + +Made by AJIOB diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index 3ae6218..f5729c3 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -5,6 +5,7 @@ class TrackPlatform_BasicConnector { +protected: std::string rxLocation; std::string txLocation; uint32_t baudRate; @@ -15,7 +16,7 @@ class TrackPlatform_BasicConnector virtual std::string read() = 0; virtual void write(const std::string& s) = 0; - virtual bool isAvailable() = 0; + virtual bool isConnected() = 0; }; #endif /* _TRACKPLATFORM_BASICCONNECTOR_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index b2d6a12..e832516 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -1,19 +1,57 @@ #include "TrackPlatform_BasicManagement.h" -void TrackPlatform_BasicManagement::move(const std::string& additionalInfo) const +void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) const { connector->write(static_cast(movementControllerID) + additionalInfo); } +void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInfo) const +{ + connector->write(static_cast(sensorsControllerID) + additionalInfo); +} + +void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) const +{ + connector->write(static_cast(servoControllerID) + additionalInfo); +} + +std::vector TrackPlatform_BasicManagement::parseStringToArray(std::string s) +{ + std::vector distancies; + size_t stringOldLen = 0; + size_t posToNextValue = 0; + do + { + distancies.push_back(std::stoul(s, &posToNextValue)); + stringOldLen = s.length(); + s = s.substr(posToNextValue + sizeof delimiter); + } while ((s != "") && (stringOldLen > s.length())); + + if (stringOldLen <= s.length()) + { + distancies.pop_back(); + } + return distancies; +} + +TrackPlatform_BasicConnector* TrackPlatform_BasicManagement::getConnector() const +{ + return connector; +} + TrackPlatform_BasicManagement::TrackPlatform_BasicManagement(TrackPlatform_BasicConnector* connector) : connector(connector) { } +TrackPlatform_BasicManagement::~TrackPlatform_BasicManagement() +{ +} + void TrackPlatform_BasicManagement::moveForward() const { std::string toSend(1, forward); - move(toSend); + sendMove(toSend); } bool TrackPlatform_BasicManagement::moveForward(double speed) const @@ -25,7 +63,7 @@ bool TrackPlatform_BasicManagement::moveForward(double speed) const std::string toSend(1, forward_speed); toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); - move(toSend); + sendMove(toSend); return true; } @@ -34,13 +72,13 @@ void TrackPlatform_BasicManagement::moveForward(uint32_t timeInMSec) const { std::string toSend(1, forward_time); toSend += std::to_string(timeInMSec); - move(toSend); + sendMove(toSend); } void TrackPlatform_BasicManagement::moveBackward() const { std::string toSend(1, back); - move(toSend); + sendMove(toSend); } bool TrackPlatform_BasicManagement::moveBackward(double speed) const @@ -52,7 +90,7 @@ bool TrackPlatform_BasicManagement::moveBackward(double speed) const std::string toSend(1, back_speed); toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); - move(toSend); + sendMove(toSend); return true; } @@ -60,19 +98,19 @@ bool TrackPlatform_BasicManagement::moveBackward(double speed) const void TrackPlatform_BasicManagement::rotateClockwise() const { std::string toSend(1, right); - move(toSend); + sendMove(toSend); } void TrackPlatform_BasicManagement::rotateAntiClockwise() const { std::string toSend(1, left); - move(toSend); + sendMove(toSend); } void TrackPlatform_BasicManagement::moveStopAll() const { std::string toSend(1, stop); - move(toSend); + sendMove(toSend); } bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double speed) const @@ -86,7 +124,69 @@ bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double toSend += std::to_string(*reinterpret_cast(&trackId)); toSend += delimiter; toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); - move(toSend); + sendMove(toSend); return true; } + +uint32_t TrackPlatform_BasicManagement::sensorDistanceGetValue(uint8_t num) const +{ + std::string toSend(1, distance_sensor); + toSend += std::to_string(num); + sendSensors(toSend); + auto answer = connector->read(); + return std::stoi(answer); +} + +std::vector TrackPlatform_BasicManagement::sensorDistanceGetAllValues() const +{ + std::string toSend(1, distance_sensor_all); + sendSensors(toSend); + return parseStringToArray(connector->read()); +} + +uint32_t TrackPlatform_BasicManagement::sensorLineGetValue(uint8_t num) const +{ + std::string toSend(1, line_sensor); + toSend += std::to_string(num); + sendSensors(toSend); + auto answer = connector->read(); + return std::stoi(answer); +} + +std::vector TrackPlatform_BasicManagement::sensorLineGetAllValues() const +{ + std::string toSend(1, line_sensor_all); + sendSensors(toSend); + return parseStringToArray(connector->read()); +} + +void TrackPlatform_BasicManagement::servoSetHorizontalAngle(uint16_t angle) const +{ + std::string toSend(1, set_horizontal_angle); + toSend += std::to_string(angle); + sendServo(toSend); +} + +void TrackPlatform_BasicManagement::servoSetVerticalAngle(uint16_t angle) const +{ + std::string toSend(1, set_vertical_angle); + toSend += std::to_string(angle); + sendServo(toSend); +} + +void TrackPlatform_BasicManagement::servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle) const +{ + std::string toSend(1, set_horiz_vertical_angles); + toSend += std::to_string(horizontalAngle); + toSend += delimiter; + toSend += std::to_string(verticalAngle); + sendServo(toSend); +} + +std::vector TrackPlatform_BasicManagement::servoGetAngles() const +{ + std::string toSend(1, get_coodrinates); + sendServo(toSend); + return parseStringToArray(connector->read()); +} diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index 09409a4..b5258bb 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -1,23 +1,33 @@ #ifndef _TRACKPLATFORM_BASICMANAGEMENT_H_ #define _TRACKPLATFORM_BASICMANAGEMENT_H_ +#include + #include "TrackPlatform_BasicConnector.h" #include "CommandsEnum.h" class TrackPlatform_BasicManagement { TrackPlatform_BasicConnector* connector; - + static const uint8_t minSpeed = 0; static const uint8_t maxSpeed = 255; static const char delimiter = ';'; protected: - void move(const std::string& additionalInfo) const; + void sendMove(const std::string& additionalInfo) const; + void sendSensors(const std::string& additionalInfo) const; + void sendServo(const std::string& additionalInfo) const; + + static std::vector parseStringToArray(std::string s); + + TrackPlatform_BasicConnector* getConnector() const; public: TrackPlatform_BasicManagement(TrackPlatform_BasicConnector* connector); + virtual ~TrackPlatform_BasicManagement(); + /* movement controller */ void moveForward() const; //speed must be in [0,1] range bool moveForward(double speed) const; @@ -34,6 +44,18 @@ class TrackPlatform_BasicManagement //speed must be in [0,1] range bool setTrackForwardSpeed(TrackID trackId, double speed) const; + + /* sensors controller */ + uint32_t sensorDistanceGetValue(uint8_t num) const; + std::vector sensorDistanceGetAllValues() const; + uint32_t sensorLineGetValue(uint8_t num) const; + std::vector sensorLineGetAllValues() const; + + /* servo controller */ + void servoSetHorizontalAngle(uint16_t angle) const; + void servoSetVerticalAngle(uint16_t angle) const; + void servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle) const; + std::vector servoGetAngles() const; }; #endif /* _TRACKPLATFORM_BASICMANAGEMENT_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp new file mode 100644 index 0000000..cf942b6 --- /dev/null +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -0,0 +1,34 @@ +#include "TrackPlatform_Manager.h" +#include "BluetoothConnector.h" + +TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate) +{ + TrackPlatform_BasicConnector* res; + + //TODO: write + switch (mode) + { + case bluetooth: + res = new BluetoothConnector(rx, tx, baudRate); + break; + default: + res = nullptr; + break; + } + + return res; +} + +TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate) : + TrackPlatform_BasicManagement(createConnectorByMode(mode, rx, tx, baudRate)) +{ +} + +TrackPlatform_Manager::~TrackPlatform_Manager() +{ + TrackPlatform_BasicConnector* connector = getConnector(); + if (connector) + { + delete connector; + } +} diff --git a/code/c++/cxx-api/TrackPlatform_Manager.h b/code/c++/cxx-api/TrackPlatform_Manager.h new file mode 100644 index 0000000..2f4b9bd --- /dev/null +++ b/code/c++/cxx-api/TrackPlatform_Manager.h @@ -0,0 +1,16 @@ +#ifndef _TRACKPLATFORM_MANAGER_H_ +#define _TRACKPLATFORM_MANAGER_H_ + +#include "TrackPlatform_BasicManagement.h" +#include "ConnectionModes.h" + +class TrackPlatform_Manager : public TrackPlatform_BasicManagement +{ + static TrackPlatform_BasicConnector* createConnectorByMode(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate); + +public: + TrackPlatform_Manager(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate); + ~TrackPlatform_Manager(); +}; + +#endif /* _TRACKPLATFORM_MANAGER_H_ */ diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 367f616..cf3165c 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -70,7 +70,18 @@ - + + $(ProjectDir)serial_support\include\;$(IncludePath) + + + $(ProjectDir)serial_support\include\;$(IncludePath) + + + $(ProjectDir)serial_support\include\;$(IncludePath) + + + $(ProjectDir)serial_support\include\;$(IncludePath) + @@ -128,13 +139,24 @@ + + + + + + + + + + + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 5eafa57..bb6dabe 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -13,6 +13,15 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {de9cad78-f264-4652-87a0-7f8536f7ef0c} + + + {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} + + + {a897fa9d-d634-41b6-a441-71b4a660fa92} + @@ -24,6 +33,24 @@ Header Files + + serial_support\header + + + serial_support\header + + + serial_support\header + + + Header Files + + + Header Files + + + Header Files + @@ -32,5 +59,20 @@ Source Files + + serial_support\source + + + serial_support\source + + + serial_support\source + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/code/c++/cxx-api/serial_support/include/serial/impl/unix.h b/code/c++/cxx-api/serial_support/include/serial/impl/unix.h new file mode 100644 index 0000000..0fb38f2 --- /dev/null +++ b/code/c++/cxx-api/serial_support/include/serial/impl/unix.h @@ -0,0 +1,221 @@ +/*! + * \file serial/impl/unix.h + * \author William Woodall + * \author John Harrison + * \version 0.1 + * + * \section LICENSE + * + * The MIT License + * + * Copyright (c) 2012 William Woodall, John Harrison + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * \section DESCRIPTION + * + * This provides a unix based pimpl for the Serial class. This implementation is + * based off termios.h and uses select for multiplexing the IO ports. + * + */ + +#if !defined(_WIN32) + +#ifndef SERIAL_IMPL_UNIX_H +#define SERIAL_IMPL_UNIX_H + +#include "serial/serial.h" + +#include + +namespace serial { + +using std::size_t; +using std::string; +using std::invalid_argument; + +using serial::SerialException; +using serial::IOException; + +class MillisecondTimer { +public: + MillisecondTimer(const uint32_t millis); + int64_t remaining(); + +private: + static timespec timespec_now(); + timespec expiry; +}; + +class serial::Serial::SerialImpl { +public: + SerialImpl (const string &port, + unsigned long baudrate, + bytesize_t bytesize, + parity_t parity, + stopbits_t stopbits, + flowcontrol_t flowcontrol); + + virtual ~SerialImpl (); + + void + open (); + + void + close (); + + bool + isOpen () const; + + size_t + available (); + + bool + waitReadable (uint32_t timeout); + + void + waitByteTimes (size_t count); + + size_t + read (uint8_t *buf, size_t size = 1); + + size_t + write (const uint8_t *data, size_t length); + + void + flush (); + + void + flushInput (); + + void + flushOutput (); + + void + sendBreak (int duration); + + void + setBreak (bool level); + + void + setRTS (bool level); + + void + setDTR (bool level); + + bool + waitForChange (); + + bool + getCTS (); + + bool + getDSR (); + + bool + getRI (); + + bool + getCD (); + + void + setPort (const string &port); + + string + getPort () const; + + void + setTimeout (Timeout &timeout); + + Timeout + getTimeout () const; + + void + setBaudrate (unsigned long baudrate); + + unsigned long + getBaudrate () const; + + void + setBytesize (bytesize_t bytesize); + + bytesize_t + getBytesize () const; + + void + setParity (parity_t parity); + + parity_t + getParity () const; + + void + setStopbits (stopbits_t stopbits); + + stopbits_t + getStopbits () const; + + void + setFlowcontrol (flowcontrol_t flowcontrol); + + flowcontrol_t + getFlowcontrol () const; + + void + readLock (); + + void + readUnlock (); + + void + writeLock (); + + void + writeUnlock (); + +protected: + void reconfigurePort (); + +private: + string port_; // Path to the file descriptor + int fd_; // The current file descriptor + + bool is_open_; + bool xonxoff_; + bool rtscts_; + + Timeout timeout_; // Timeout for read operations + unsigned long baudrate_; // Baudrate + uint32_t byte_time_ns_; // Nanoseconds to transmit/receive a single byte + + parity_t parity_; // Parity + bytesize_t bytesize_; // Size of the bytes + stopbits_t stopbits_; // Stop Bits + flowcontrol_t flowcontrol_; // Flow Control + + // Mutex used to lock the read functions + pthread_mutex_t read_mutex; + // Mutex used to lock the write functions + pthread_mutex_t write_mutex; +}; + +} + +#endif // SERIAL_IMPL_UNIX_H + +#endif // !defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/include/serial/impl/win.h b/code/c++/cxx-api/serial_support/include/serial/impl/win.h new file mode 100644 index 0000000..2c0c6cd --- /dev/null +++ b/code/c++/cxx-api/serial_support/include/serial/impl/win.h @@ -0,0 +1,207 @@ +/*! + * \file serial/impl/windows.h + * \author William Woodall + * \author John Harrison + * \version 0.1 + * + * \section LICENSE + * + * The MIT License + * + * Copyright (c) 2012 William Woodall, John Harrison + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * \section DESCRIPTION + * + * This provides a windows implementation of the Serial class interface. + * + */ + +#if defined(_WIN32) + +#ifndef SERIAL_IMPL_WINDOWS_H +#define SERIAL_IMPL_WINDOWS_H + +#include "serial/serial.h" + +#include "windows.h" + +namespace serial { + +using std::string; +using std::wstring; +using std::invalid_argument; + +using serial::SerialException; +using serial::IOException; + +class serial::Serial::SerialImpl { +public: + SerialImpl (const string &port, + unsigned long baudrate, + bytesize_t bytesize, + parity_t parity, + stopbits_t stopbits, + flowcontrol_t flowcontrol); + + virtual ~SerialImpl (); + + void + open (); + + void + close (); + + bool + isOpen () const; + + size_t + available (); + + bool + waitReadable (uint32_t timeout); + + void + waitByteTimes (size_t count); + + size_t + read (uint8_t *buf, size_t size = 1); + + size_t + write (const uint8_t *data, size_t length); + + void + flush (); + + void + flushInput (); + + void + flushOutput (); + + void + sendBreak (int duration); + + void + setBreak (bool level); + + void + setRTS (bool level); + + void + setDTR (bool level); + + bool + waitForChange (); + + bool + getCTS (); + + bool + getDSR (); + + bool + getRI (); + + bool + getCD (); + + void + setPort (const string &port); + + string + getPort () const; + + void + setTimeout (Timeout &timeout); + + Timeout + getTimeout () const; + + void + setBaudrate (unsigned long baudrate); + + unsigned long + getBaudrate () const; + + void + setBytesize (bytesize_t bytesize); + + bytesize_t + getBytesize () const; + + void + setParity (parity_t parity); + + parity_t + getParity () const; + + void + setStopbits (stopbits_t stopbits); + + stopbits_t + getStopbits () const; + + void + setFlowcontrol (flowcontrol_t flowcontrol); + + flowcontrol_t + getFlowcontrol () const; + + void + readLock (); + + void + readUnlock (); + + void + writeLock (); + + void + writeUnlock (); + +protected: + void reconfigurePort (); + +private: + wstring port_; // Path to the file descriptor + HANDLE fd_; + + bool is_open_; + + Timeout timeout_; // Timeout for read operations + unsigned long baudrate_; // Baudrate + + parity_t parity_; // Parity + bytesize_t bytesize_; // Size of the bytes + stopbits_t stopbits_; // Stop Bits + flowcontrol_t flowcontrol_; // Flow Control + + // Mutex used to lock the read functions + HANDLE read_mutex; + // Mutex used to lock the write functions + HANDLE write_mutex; +}; + +} + +#endif // SERIAL_IMPL_WINDOWS_H + +#endif // if defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/include/serial/serial.h b/code/c++/cxx-api/serial_support/include/serial/serial.h new file mode 100644 index 0000000..1385659 --- /dev/null +++ b/code/c++/cxx-api/serial_support/include/serial/serial.h @@ -0,0 +1,775 @@ +/*! + * \file serial/serial.h + * \author William Woodall + * \author John Harrison + * \version 0.1 + * + * \section LICENSE + * + * The MIT License + * + * Copyright (c) 2012 William Woodall + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * \section DESCRIPTION + * + * This provides a cross platform interface for interacting with Serial Ports. + */ + +#ifndef SERIAL_H +#define SERIAL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ +__LINE__, (message) ) + +namespace serial { + +/*! + * Enumeration defines the possible bytesizes for the serial port. + */ +typedef enum { + fivebits = 5, + sixbits = 6, + sevenbits = 7, + eightbits = 8 +} bytesize_t; + +/*! + * Enumeration defines the possible parity types for the serial port. + */ +typedef enum { + parity_none = 0, + parity_odd = 1, + parity_even = 2, + parity_mark = 3, + parity_space = 4 +} parity_t; + +/*! + * Enumeration defines the possible stopbit types for the serial port. + */ +typedef enum { + stopbits_one = 1, + stopbits_two = 2, + stopbits_one_point_five +} stopbits_t; + +/*! + * Enumeration defines the possible flowcontrol types for the serial port. + */ +typedef enum { + flowcontrol_none = 0, + flowcontrol_software, + flowcontrol_hardware +} flowcontrol_t; + +/*! + * Structure for setting the timeout of the serial port, times are + * in milliseconds. + * + * In order to disable the interbyte timeout, set it to Timeout::max(). + */ +struct Timeout { +#ifdef max +# undef max +#endif + static uint32_t max() {return std::numeric_limits::max();} + /*! + * Convenience function to generate Timeout structs using a + * single absolute timeout. + * + * \param timeout A long that defines the time in milliseconds until a + * timeout occurs after a call to read or write is made. + * + * \return Timeout struct that represents this simple timeout provided. + */ + static Timeout simpleTimeout(uint32_t timeout) { + return Timeout(max(), timeout, 0, timeout, 0); + } + + /*! Number of milliseconds between bytes received to timeout on. */ + uint32_t inter_byte_timeout; + /*! A constant number of milliseconds to wait after calling read. */ + uint32_t read_timeout_constant; + /*! A multiplier against the number of requested bytes to wait after + * calling read. + */ + uint32_t read_timeout_multiplier; + /*! A constant number of milliseconds to wait after calling write. */ + uint32_t write_timeout_constant; + /*! A multiplier against the number of requested bytes to wait after + * calling write. + */ + uint32_t write_timeout_multiplier; + + explicit Timeout (uint32_t inter_byte_timeout_=0, + uint32_t read_timeout_constant_=0, + uint32_t read_timeout_multiplier_=0, + uint32_t write_timeout_constant_=0, + uint32_t write_timeout_multiplier_=0) + : inter_byte_timeout(inter_byte_timeout_), + read_timeout_constant(read_timeout_constant_), + read_timeout_multiplier(read_timeout_multiplier_), + write_timeout_constant(write_timeout_constant_), + write_timeout_multiplier(write_timeout_multiplier_) + {} +}; + +/*! + * Class that provides a portable serial port interface. + */ +class Serial { +public: + /*! + * Creates a Serial object and opens the port if a port is specified, + * otherwise it remains closed until serial::Serial::open is called. + * + * \param port A std::string containing the address of the serial port, + * which would be something like 'COM1' on Windows and '/dev/ttyS0' + * on Linux. + * + * \param baudrate An unsigned 32-bit integer that represents the baudrate + * + * \param timeout A serial::Timeout struct that defines the timeout + * conditions for the serial port. \see serial::Timeout + * + * \param bytesize Size of each byte in the serial transmission of data, + * default is eightbits, possible values are: fivebits, sixbits, sevenbits, + * eightbits + * + * \param parity Method of parity, default is parity_none, possible values + * are: parity_none, parity_odd, parity_even + * + * \param stopbits Number of stop bits used, default is stopbits_one, + * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two + * + * \param flowcontrol Type of flowcontrol used, default is + * flowcontrol_none, possible values are: flowcontrol_none, + * flowcontrol_software, flowcontrol_hardware + * + * \throw serial::PortNotOpenedException + * \throw serial::IOException + * \throw std::invalid_argument + */ + Serial (const std::string &port = "", + uint32_t baudrate = 9600, + Timeout timeout = Timeout(), + bytesize_t bytesize = eightbits, + parity_t parity = parity_none, + stopbits_t stopbits = stopbits_one, + flowcontrol_t flowcontrol = flowcontrol_none); + + /*! Destructor */ + virtual ~Serial (); + + /*! + * Opens the serial port as long as the port is set and the port isn't + * already open. + * + * If the port is provided to the constructor then an explicit call to open + * is not needed. + * + * \see Serial::Serial + * + * \throw std::invalid_argument + * \throw serial::SerialException + * \throw serial::IOException + */ + void + open (); + + /*! Gets the open status of the serial port. + * + * \return Returns true if the port is open, false otherwise. + */ + bool + isOpen () const; + + /*! Closes the serial port. */ + void + close (); + + /*! Return the number of characters in the buffer. */ + size_t + available (); + + /*! Block until there is serial data to read or read_timeout_constant + * number of milliseconds have elapsed. The return value is true when + * the function exits with the port in a readable state, false otherwise + * (due to timeout or select interruption). */ + bool + waitReadable (); + + /*! Block for a period of time corresponding to the transmission time of + * count characters at present serial settings. This may be used in con- + * junction with waitReadable to read larger blocks of data from the + * port. */ + void + waitByteTimes (size_t count); + + /*! Read a given amount of bytes from the serial port into a given buffer. + * + * The read function will return in one of three cases: + * * The number of requested bytes was read. + * * In this case the number of bytes requested will match the size_t + * returned by read. + * * A timeout occurred, in this case the number of bytes read will not + * match the amount requested, but no exception will be thrown. One of + * two possible timeouts occurred: + * * The inter byte timeout expired, this means that number of + * milliseconds elapsed between receiving bytes from the serial port + * exceeded the inter byte timeout. + * * The total timeout expired, which is calculated by multiplying the + * read timeout multiplier by the number of requested bytes and then + * added to the read timeout constant. If that total number of + * milliseconds elapses after the initial call to read a timeout will + * occur. + * * An exception occurred, in this case an actual exception will be thrown. + * + * \param buffer An uint8_t array of at least the requested size. + * \param size A size_t defining how many bytes to be read. + * + * \return A size_t representing the number of bytes read as a result of the + * call to read. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + size_t + read (uint8_t *buffer, size_t size); + + /*! Read a given amount of bytes from the serial port into a give buffer. + * + * \param buffer A reference to a std::vector of uint8_t. + * \param size A size_t defining how many bytes to be read. + * + * \return A size_t representing the number of bytes read as a result of the + * call to read. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + size_t + read (std::vector &buffer, size_t size = 1); + + /*! Read a given amount of bytes from the serial port into a give buffer. + * + * \param buffer A reference to a std::string. + * \param size A size_t defining how many bytes to be read. + * + * \return A size_t representing the number of bytes read as a result of the + * call to read. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + size_t + read (std::string &buffer, size_t size = 1); + + /*! Read a given amount of bytes from the serial port and return a string + * containing the data. + * + * \param size A size_t defining how many bytes to be read. + * + * \return A std::string containing the data read from the port. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + std::string + read (size_t size = 1); + + /*! Reads in a line or until a given delimiter has been processed. + * + * Reads from the serial port until a single line has been read. + * + * \param buffer A std::string reference used to store the data. + * \param size A maximum length of a line, defaults to 65536 (2^16) + * \param eol A string to match against for the EOL. + * + * \return A size_t representing the number of bytes read. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + size_t + readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); + + /*! Reads in a line or until a given delimiter has been processed. + * + * Reads from the serial port until a single line has been read. + * + * \param size A maximum length of a line, defaults to 65536 (2^16) + * \param eol A string to match against for the EOL. + * + * \return A std::string containing the line. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + std::string + readline (size_t size = 65536, std::string eol = "\n"); + + /*! Reads in multiple lines until the serial port times out. + * + * This requires a timeout > 0 before it can be run. It will read until a + * timeout occurs and return a list of strings. + * + * \param size A maximum length of combined lines, defaults to 65536 (2^16) + * + * \param eol A string to match against for the EOL. + * + * \return A vector containing the lines. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + */ + std::vector + readlines (size_t size = 65536, std::string eol = "\n"); + + /*! Write a string to the serial port. + * + * \param data A const reference containing the data to be written + * to the serial port. + * + * \param size A size_t that indicates how many bytes should be written from + * the given data buffer. + * + * \return A size_t representing the number of bytes actually written to + * the serial port. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + * \throw serial::IOException + */ + size_t + write (const uint8_t *data, size_t size); + + /*! Write a string to the serial port. + * + * \param data A const reference containing the data to be written + * to the serial port. + * + * \return A size_t representing the number of bytes actually written to + * the serial port. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + * \throw serial::IOException + */ + size_t + write (const std::vector &data); + + /*! Write a string to the serial port. + * + * \param data A const reference containing the data to be written + * to the serial port. + * + * \return A size_t representing the number of bytes actually written to + * the serial port. + * + * \throw serial::PortNotOpenedException + * \throw serial::SerialException + * \throw serial::IOException + */ + size_t + write (const std::string &data); + + /*! Sets the serial port identifier. + * + * \param port A const std::string reference containing the address of the + * serial port, which would be something like 'COM1' on Windows and + * '/dev/ttyS0' on Linux. + * + * \throw std::invalid_argument + */ + void + setPort (const std::string &port); + + /*! Gets the serial port identifier. + * + * \see Serial::setPort + * + * \throw std::invalid_argument + */ + std::string + getPort () const; + + /*! Sets the timeout for reads and writes using the Timeout struct. + * + * There are two timeout conditions described here: + * * The inter byte timeout: + * * The inter_byte_timeout component of serial::Timeout defines the + * maximum amount of time, in milliseconds, between receiving bytes on + * the serial port that can pass before a timeout occurs. Setting this + * to zero will prevent inter byte timeouts from occurring. + * * Total time timeout: + * * The constant and multiplier component of this timeout condition, + * for both read and write, are defined in serial::Timeout. This + * timeout occurs if the total time since the read or write call was + * made exceeds the specified time in milliseconds. + * * The limit is defined by multiplying the multiplier component by the + * number of requested bytes and adding that product to the constant + * component. In this way if you want a read call, for example, to + * timeout after exactly one second regardless of the number of bytes + * you asked for then set the read_timeout_constant component of + * serial::Timeout to 1000 and the read_timeout_multiplier to zero. + * This timeout condition can be used in conjunction with the inter + * byte timeout condition with out any problems, timeout will simply + * occur when one of the two timeout conditions is met. This allows + * users to have maximum control over the trade-off between + * responsiveness and efficiency. + * + * Read and write functions will return in one of three cases. When the + * reading or writing is complete, when a timeout occurs, or when an + * exception occurs. + * + * A timeout of 0 enables non-blocking mode. + * + * \param timeout A serial::Timeout struct containing the inter byte + * timeout, and the read and write timeout constants and multipliers. + * + * \see serial::Timeout + */ + void + setTimeout (Timeout &timeout); + + /*! Sets the timeout for reads and writes. */ + void + setTimeout (uint32_t inter_byte_timeout, uint32_t read_timeout_constant, + uint32_t read_timeout_multiplier, uint32_t write_timeout_constant, + uint32_t write_timeout_multiplier) + { + Timeout timeout(inter_byte_timeout, read_timeout_constant, + read_timeout_multiplier, write_timeout_constant, + write_timeout_multiplier); + return setTimeout(timeout); + } + + /*! Gets the timeout for reads in seconds. + * + * \return A Timeout struct containing the inter_byte_timeout, and read + * and write timeout constants and multipliers. + * + * \see Serial::setTimeout + */ + Timeout + getTimeout () const; + + /*! Sets the baudrate for the serial port. + * + * Possible baudrates depends on the system but some safe baudrates include: + * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, + * 57600, 115200 + * Some other baudrates that are supported by some comports: + * 128000, 153600, 230400, 256000, 460800, 921600 + * + * \param baudrate An integer that sets the baud rate for the serial port. + * + * \throw std::invalid_argument + */ + void + setBaudrate (uint32_t baudrate); + + /*! Gets the baudrate for the serial port. + * + * \return An integer that sets the baud rate for the serial port. + * + * \see Serial::setBaudrate + * + * \throw std::invalid_argument + */ + uint32_t + getBaudrate () const; + + /*! Sets the bytesize for the serial port. + * + * \param bytesize Size of each byte in the serial transmission of data, + * default is eightbits, possible values are: fivebits, sixbits, sevenbits, + * eightbits + * + * \throw std::invalid_argument + */ + void + setBytesize (bytesize_t bytesize); + + /*! Gets the bytesize for the serial port. + * + * \see Serial::setBytesize + * + * \throw std::invalid_argument + */ + bytesize_t + getBytesize () const; + + /*! Sets the parity for the serial port. + * + * \param parity Method of parity, default is parity_none, possible values + * are: parity_none, parity_odd, parity_even + * + * \throw std::invalid_argument + */ + void + setParity (parity_t parity); + + /*! Gets the parity for the serial port. + * + * \see Serial::setParity + * + * \throw std::invalid_argument + */ + parity_t + getParity () const; + + /*! Sets the stopbits for the serial port. + * + * \param stopbits Number of stop bits used, default is stopbits_one, + * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two + * + * \throw std::invalid_argument + */ + void + setStopbits (stopbits_t stopbits); + + /*! Gets the stopbits for the serial port. + * + * \see Serial::setStopbits + * + * \throw std::invalid_argument + */ + stopbits_t + getStopbits () const; + + /*! Sets the flow control for the serial port. + * + * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, + * possible values are: flowcontrol_none, flowcontrol_software, + * flowcontrol_hardware + * + * \throw std::invalid_argument + */ + void + setFlowcontrol (flowcontrol_t flowcontrol); + + /*! Gets the flow control for the serial port. + * + * \see Serial::setFlowcontrol + * + * \throw std::invalid_argument + */ + flowcontrol_t + getFlowcontrol () const; + + /*! Flush the input and output buffers */ + void + flush (); + + /*! Flush only the input buffer */ + void + flushInput (); + + /*! Flush only the output buffer */ + void + flushOutput (); + + /*! Sends the RS-232 break signal. See tcsendbreak(3). */ + void + sendBreak (int duration); + + /*! Set the break condition to a given level. Defaults to true. */ + void + setBreak (bool level = true); + + /*! Set the RTS handshaking line to the given level. Defaults to true. */ + void + setRTS (bool level = true); + + /*! Set the DTR handshaking line to the given level. Defaults to true. */ + void + setDTR (bool level = true); + + /*! + * Blocks until CTS, DSR, RI, CD changes or something interrupts it. + * + * Can throw an exception if an error occurs while waiting. + * You can check the status of CTS, DSR, RI, and CD once this returns. + * Uses TIOCMIWAIT via ioctl if available (mostly only on Linux) with a + * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a + * polling method is used which can give +-2ms. + * + * \return Returns true if one of the lines changed, false if something else + * occurred. + * + * \throw SerialException + */ + bool + waitForChange (); + + /*! Returns the current status of the CTS line. */ + bool + getCTS (); + + /*! Returns the current status of the DSR line. */ + bool + getDSR (); + + /*! Returns the current status of the RI line. */ + bool + getRI (); + + /*! Returns the current status of the CD line. */ + bool + getCD (); + +private: + // Disable copy constructors + Serial(const Serial&); + Serial& operator=(const Serial&); + + // Pimpl idiom, d_pointer + class SerialImpl; + SerialImpl *pimpl_; + + // Scoped Lock Classes + class ScopedReadLock; + class ScopedWriteLock; + + // Read common function + size_t + read_ (uint8_t *buffer, size_t size); + // Write common function + size_t + write_ (const uint8_t *data, size_t length); + +}; + +class SerialException : public std::exception +{ + // Disable copy constructors + SerialException& operator=(const SerialException&); + std::string e_what_; +public: + SerialException (const char *description) { + std::stringstream ss; + ss << "SerialException " << description << " failed."; + e_what_ = ss.str(); + } + SerialException (const SerialException& other) : e_what_(other.e_what_) {} + virtual ~SerialException() throw() {} + virtual const char* what () const throw () { + return e_what_.c_str(); + } +}; + +class IOException : public std::exception +{ + // Disable copy constructors + IOException& operator=(const IOException&); + std::string file_; + int line_; + std::string e_what_; + int errno_; +public: + explicit IOException (std::string file, int line, int errnum) + : file_(file), line_(line), errno_(errnum) { + std::stringstream ss; +#if defined(_WIN32) && !defined(__MINGW32__) + char error_str [1024]; + strerror_s(error_str, 1024, errnum); +#else + char * error_str = strerror(errnum); +#endif + ss << "IO Exception (" << errno_ << "): " << error_str; + ss << ", file " << file_ << ", line " << line_ << "."; + e_what_ = ss.str(); + } + explicit IOException (std::string file, int line, const char * description) + : file_(file), line_(line), errno_(0) { + std::stringstream ss; + ss << "IO Exception: " << description; + ss << ", file " << file_ << ", line " << line_ << "."; + e_what_ = ss.str(); + } + virtual ~IOException() throw() {} + IOException (const IOException& other) : line_(other.line_), e_what_(other.e_what_), errno_(other.errno_) {} + + int getErrorNumber () const { return errno_; } + + virtual const char* what () const throw () { + return e_what_.c_str(); + } +}; + +class PortNotOpenedException : public std::exception +{ + // Disable copy constructors + const PortNotOpenedException& operator=(PortNotOpenedException); + std::string e_what_; +public: + PortNotOpenedException (const char * description) { + std::stringstream ss; + ss << "PortNotOpenedException " << description << " failed."; + e_what_ = ss.str(); + } + PortNotOpenedException (const PortNotOpenedException& other) : e_what_(other.e_what_) {} + virtual ~PortNotOpenedException() throw() {} + virtual const char* what () const throw () { + return e_what_.c_str(); + } +}; + +/*! + * Structure that describes a serial device. + */ +struct PortInfo { + + /*! Address of the serial port (this can be passed to the constructor of Serial). */ + std::string port; + + /*! Human readable description of serial device if available. */ + std::string description; + + /*! Hardware ID (e.g. VID:PID of USB serial devices) or "n/a" if not available. */ + std::string hardware_id; + +}; + +/* Lists the serial ports available on the system + * + * Returns a vector of available serial ports, each represented + * by a serial::PortInfo data structure: + * + * \return vector of serial::PortInfo. + */ +std::vector +list_ports(); + +} // namespace serial + +#endif diff --git a/code/c++/cxx-api/serial_support/include/serial/v8stdint.h b/code/c++/cxx-api/serial_support/include/serial/v8stdint.h new file mode 100644 index 0000000..f3be96b --- /dev/null +++ b/code/c++/cxx-api/serial_support/include/serial/v8stdint.h @@ -0,0 +1,57 @@ +// This header is from the v8 google project: +// http://code.google.com/p/v8/source/browse/trunk/include/v8stdint.h + +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Load definitions of standard types. + +#ifndef V8STDINT_H_ +#define V8STDINT_H_ + +#include +#include + +#if defined(_WIN32) && !defined(__MINGW32__) + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; // NOLINT +typedef unsigned short uint16_t; // NOLINT +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +// intptr_t and friends are defined in crtdefs.h through stdio.h. + +#else + +#include + +#endif + +#endif // V8STDINT_H_ diff --git a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc new file mode 100644 index 0000000..9779d5e --- /dev/null +++ b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc @@ -0,0 +1,335 @@ +#if defined(__linux__) + +/* + * Copyright (c) 2014 Craig Lilley + * This software is made available under the terms of the MIT licence. + * A copy of the licence can be obtained from: + * http://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "serial/serial.h" + +using serial::PortInfo; +using std::istringstream; +using std::ifstream; +using std::getline; +using std::vector; +using std::string; +using std::cout; +using std::endl; + +static vector glob(const vector& patterns); +static string basename(const string& path); +static string dirname(const string& path); +static bool path_exists(const string& path); +static string realpath(const string& path); +static string usb_sysfs_friendly_name(const string& sys_usb_path); +static vector get_sysfs_info(const string& device_path); +static string read_line(const string& file); +static string usb_sysfs_hw_string(const string& sysfs_path); +static string format(const char* format, ...); + +vector +glob(const vector& patterns) +{ + vector paths_found; + + if(patterns.size() == 0) + return paths_found; + + glob_t glob_results; + + int glob_retval = glob(patterns[0].c_str(), 0, NULL, &glob_results); + + vector::const_iterator iter = patterns.begin(); + + while(++iter != patterns.end()) + { + glob_retval = glob(iter->c_str(), GLOB_APPEND, NULL, &glob_results); + } + + for(int path_index = 0; path_index < glob_results.gl_pathc; path_index++) + { + paths_found.push_back(glob_results.gl_pathv[path_index]); + } + + globfree(&glob_results); + + return paths_found; +} + +string +basename(const string& path) +{ + size_t pos = path.rfind("/"); + + if(pos == std::string::npos) + return path; + + return string(path, pos+1, string::npos); +} + +string +dirname(const string& path) +{ + size_t pos = path.rfind("/"); + + if(pos == std::string::npos) + return path; + else if(pos == 0) + return "/"; + + return string(path, 0, pos); +} + +bool +path_exists(const string& path) +{ + struct stat sb; + + if( stat(path.c_str(), &sb ) == 0 ) + return true; + + return false; +} + +string +realpath(const string& path) +{ + char* real_path = realpath(path.c_str(), NULL); + + string result; + + if(real_path != NULL) + { + result = real_path; + + free(real_path); + } + + return result; +} + +string +usb_sysfs_friendly_name(const string& sys_usb_path) +{ + unsigned int device_number = 0; + + istringstream( read_line(sys_usb_path + "/devnum") ) >> device_number; + + string manufacturer = read_line( sys_usb_path + "/manufacturer" ); + + string product = read_line( sys_usb_path + "/product" ); + + string serial = read_line( sys_usb_path + "/serial" ); + + if( manufacturer.empty() && product.empty() && serial.empty() ) + return ""; + + return format("%s %s %s", manufacturer.c_str(), product.c_str(), serial.c_str() ); +} + +vector +get_sysfs_info(const string& device_path) +{ + string device_name = basename( device_path ); + + string friendly_name; + + string hardware_id; + + string sys_device_path = format( "/sys/class/tty/%s/device", device_name.c_str() ); + + if( device_name.compare(0,6,"ttyUSB") == 0 ) + { + sys_device_path = dirname( dirname( realpath( sys_device_path ) ) ); + + if( path_exists( sys_device_path ) ) + { + friendly_name = usb_sysfs_friendly_name( sys_device_path ); + + hardware_id = usb_sysfs_hw_string( sys_device_path ); + } + } + else if( device_name.compare(0,6,"ttyACM") == 0 ) + { + sys_device_path = dirname( realpath( sys_device_path ) ); + + if( path_exists( sys_device_path ) ) + { + friendly_name = usb_sysfs_friendly_name( sys_device_path ); + + hardware_id = usb_sysfs_hw_string( sys_device_path ); + } + } + else + { + // Try to read ID string of PCI device + + string sys_id_path = sys_device_path + "/id"; + + if( path_exists( sys_id_path ) ) + hardware_id = read_line( sys_id_path ); + } + + if( friendly_name.empty() ) + friendly_name = device_name; + + if( hardware_id.empty() ) + hardware_id = "n/a"; + + vector result; + result.push_back(friendly_name); + result.push_back(hardware_id); + + return result; +} + +string +read_line(const string& file) +{ + ifstream ifs(file.c_str(), ifstream::in); + + string line; + + if(ifs) + { + getline(ifs, line); + } + + return line; +} + +string +format(const char* format, ...) +{ + va_list ap; + + size_t buffer_size_bytes = 256; + + string result; + + char* buffer = (char*)malloc(buffer_size_bytes); + + if( buffer == NULL ) + return result; + + bool done = false; + + unsigned int loop_count = 0; + + while(!done) + { + va_start(ap, format); + + int return_value = vsnprintf(buffer, buffer_size_bytes, format, ap); + + if( return_value < 0 ) + { + done = true; + } + else if( return_value >= buffer_size_bytes ) + { + // Realloc and try again. + + buffer_size_bytes = return_value + 1; + + char* new_buffer_ptr = (char*)realloc(buffer, buffer_size_bytes); + + if( new_buffer_ptr == NULL ) + { + done = true; + } + else + { + buffer = new_buffer_ptr; + } + } + else + { + result = buffer; + done = true; + } + + va_end(ap); + + if( ++loop_count > 5 ) + done = true; + } + + free(buffer); + + return result; +} + +string +usb_sysfs_hw_string(const string& sysfs_path) +{ + string serial_number = read_line( sysfs_path + "/serial" ); + + if( serial_number.length() > 0 ) + { + serial_number = format( "SNR=%s", serial_number.c_str() ); + } + + string vid = read_line( sysfs_path + "/idVendor" ); + + string pid = read_line( sysfs_path + "/idProduct" ); + + return format("USB VID:PID=%s:%s %s", vid.c_str(), pid.c_str(), serial_number.c_str() ); +} + +vector +serial::list_ports() +{ + vector results; + + vector search_globs; + search_globs.push_back("/dev/ttyACM*"); + search_globs.push_back("/dev/ttyS*"); + search_globs.push_back("/dev/ttyUSB*"); + search_globs.push_back("/dev/tty.*"); + search_globs.push_back("/dev/cu.*"); + + vector devices_found = glob( search_globs ); + + vector::iterator iter = devices_found.begin(); + + while( iter != devices_found.end() ) + { + string device = *iter++; + + vector sysfs_info = get_sysfs_info( device ); + + string friendly_name = sysfs_info[0]; + + string hardware_id = sysfs_info[1]; + + PortInfo device_entry; + device_entry.port = device; + device_entry.description = friendly_name; + device_entry.hardware_id = hardware_id; + + results.push_back( device_entry ); + + } + + return results; +} + +#endif // defined(__linux__) diff --git a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc new file mode 100644 index 0000000..333c55c --- /dev/null +++ b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc @@ -0,0 +1,286 @@ +#if defined(__APPLE__) + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "serial/serial.h" + +using serial::PortInfo; +using std::string; +using std::vector; + +#define HARDWARE_ID_STRING_LENGTH 128 + +string cfstring_to_string( CFStringRef cfstring ); +string get_device_path( io_object_t& serial_port ); +string get_class_name( io_object_t& obj ); +io_registry_entry_t get_parent_iousb_device( io_object_t& serial_port ); +string get_string_property( io_object_t& device, const char* property ); +uint16_t get_int_property( io_object_t& device, const char* property ); +string rtrim(const string& str); + +string +cfstring_to_string( CFStringRef cfstring ) +{ + char cstring[MAXPATHLEN]; + string result; + + if( cfstring ) + { + Boolean success = CFStringGetCString( cfstring, + cstring, + sizeof(cstring), + kCFStringEncodingASCII ); + + if( success ) + result = cstring; + } + + return result; +} + +string +get_device_path( io_object_t& serial_port ) +{ + CFTypeRef callout_path; + string device_path; + + callout_path = IORegistryEntryCreateCFProperty( serial_port, + CFSTR(kIOCalloutDeviceKey), + kCFAllocatorDefault, + 0 ); + + if (callout_path) + { + if( CFGetTypeID(callout_path) == CFStringGetTypeID() ) + device_path = cfstring_to_string( static_cast(callout_path) ); + + CFRelease(callout_path); + } + + return device_path; +} + +string +get_class_name( io_object_t& obj ) +{ + string result; + io_name_t class_name; + kern_return_t kern_result; + + kern_result = IOObjectGetClass( obj, class_name ); + + if( kern_result == KERN_SUCCESS ) + result = class_name; + + return result; +} + +io_registry_entry_t +get_parent_iousb_device( io_object_t& serial_port ) +{ + io_object_t device = serial_port; + io_registry_entry_t parent = 0; + io_registry_entry_t result = 0; + kern_return_t kern_result = KERN_FAILURE; + string name = get_class_name(device); + + // Walk the IO Registry tree looking for this devices parent IOUSBDevice. + while( name != "IOUSBDevice" ) + { + kern_result = IORegistryEntryGetParentEntry( device, + kIOServicePlane, + &parent ); + + if(kern_result != KERN_SUCCESS) + { + result = 0; + break; + } + + device = parent; + + name = get_class_name(device); + } + + if(kern_result == KERN_SUCCESS) + result = device; + + return result; +} + +string +get_string_property( io_object_t& device, const char* property ) +{ + string property_name; + + if( device ) + { + CFStringRef property_as_cfstring = CFStringCreateWithCString ( + kCFAllocatorDefault, + property, + kCFStringEncodingASCII ); + + CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty( + device, + property_as_cfstring, + kCFAllocatorDefault, + 0 ); + + if( name_as_cfstring ) + { + if( CFGetTypeID(name_as_cfstring) == CFStringGetTypeID() ) + property_name = cfstring_to_string( static_cast(name_as_cfstring) ); + + CFRelease(name_as_cfstring); + } + + if(property_as_cfstring) + CFRelease(property_as_cfstring); + } + + return property_name; +} + +uint16_t +get_int_property( io_object_t& device, const char* property ) +{ + uint16_t result = 0; + + if( device ) + { + CFStringRef property_as_cfstring = CFStringCreateWithCString ( + kCFAllocatorDefault, + property, + kCFStringEncodingASCII ); + + CFTypeRef number = IORegistryEntryCreateCFProperty( device, + property_as_cfstring, + kCFAllocatorDefault, + 0 ); + + if(property_as_cfstring) + CFRelease(property_as_cfstring); + + if( number ) + { + if( CFGetTypeID(number) == CFNumberGetTypeID() ) + { + bool success = CFNumberGetValue( static_cast(number), + kCFNumberSInt16Type, + &result ); + + if( !success ) + result = 0; + } + + CFRelease(number); + } + + } + + return result; +} + +string rtrim(const string& str) +{ + string result = str; + + string whitespace = " \t\f\v\n\r"; + + std::size_t found = result.find_last_not_of(whitespace); + + if (found != std::string::npos) + result.erase(found+1); + else + result.clear(); + + return result; +} + +vector +serial::list_ports(void) +{ + vector devices_found; + CFMutableDictionaryRef classes_to_match; + io_iterator_t serial_port_iterator; + io_object_t serial_port; + mach_port_t master_port; + kern_return_t kern_result; + + kern_result = IOMasterPort(MACH_PORT_NULL, &master_port); + + if(kern_result != KERN_SUCCESS) + return devices_found; + + classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue); + + if (classes_to_match == NULL) + return devices_found; + + CFDictionarySetValue( classes_to_match, + CFSTR(kIOSerialBSDTypeKey), + CFSTR(kIOSerialBSDAllTypes) ); + + kern_result = IOServiceGetMatchingServices(master_port, classes_to_match, &serial_port_iterator); + + if (KERN_SUCCESS != kern_result) + return devices_found; + + while ( (serial_port = IOIteratorNext(serial_port_iterator)) ) + { + string device_path = get_device_path( serial_port ); + io_registry_entry_t parent = get_parent_iousb_device( serial_port ); + IOObjectRelease(serial_port); + + if( device_path.empty() ) + continue; + + PortInfo port_info; + port_info.port = device_path; + port_info.description = "n/a"; + port_info.hardware_id = "n/a"; + + string device_name = rtrim( get_string_property( parent, "USB Product Name" ) ); + string vendor_name = rtrim( get_string_property( parent, "USB Vendor Name") ); + string description = rtrim( vendor_name + " " + device_name ); + if( !description.empty() ) + port_info.description = description; + + string serial_number = rtrim(get_string_property( parent, "USB Serial Number" ) ); + uint16_t vendor_id = get_int_property( parent, "idVendor" ); + uint16_t product_id = get_int_property( parent, "idProduct" ); + + if( vendor_id && product_id ) + { + char cstring[HARDWARE_ID_STRING_LENGTH]; + + if(serial_number.empty()) + serial_number = "None"; + + int ret = snprintf( cstring, HARDWARE_ID_STRING_LENGTH, "USB VID:PID=%04x:%04x SNR=%s", + vendor_id, + product_id, + serial_number.c_str() ); + + if( (ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH) ) + port_info.hardware_id = cstring; + } + + devices_found.push_back(port_info); + } + + IOObjectRelease(serial_port_iterator); + return devices_found; +} + +#endif // defined(__APPLE__) diff --git a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc new file mode 100644 index 0000000..7da40c4 --- /dev/null +++ b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc @@ -0,0 +1,152 @@ +#if defined(_WIN32) + +/* + * Copyright (c) 2014 Craig Lilley + * This software is made available under the terms of the MIT licence. + * A copy of the licence can be obtained from: + * http://opensource.org/licenses/MIT + */ + +#include "serial/serial.h" +#include +#include +#include +#include +#include +#include + +using serial::PortInfo; +using std::vector; +using std::string; + +static const DWORD port_name_max_length = 256; +static const DWORD friendly_name_max_length = 256; +static const DWORD hardware_id_max_length = 256; + +// Convert a wide Unicode string to an UTF8 string +std::string utf8_encode(const std::wstring &wstr) +{ + int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); + std::string strTo( size_needed, 0 ); + WideCharToMultiByte (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); + return strTo; +} + +vector +serial::list_ports() +{ + vector devices_found; + + HDEVINFO device_info_set = SetupDiGetClassDevs( + (const GUID *) &GUID_DEVCLASS_PORTS, + NULL, + NULL, + DIGCF_PRESENT); + + unsigned int device_info_set_index = 0; + SP_DEVINFO_DATA device_info_data; + + device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + + while(SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data)) + { + device_info_set_index++; + + // Get port name + + HKEY hkey = SetupDiOpenDevRegKey( + device_info_set, + &device_info_data, + DICS_FLAG_GLOBAL, + 0, + DIREG_DEV, + KEY_READ); + + TCHAR port_name[port_name_max_length]; + DWORD port_name_length = port_name_max_length; + + LONG return_code = RegQueryValueEx( + hkey, + _T("PortName"), + NULL, + NULL, + (LPBYTE)port_name, + &port_name_length); + + RegCloseKey(hkey); + + if(return_code != EXIT_SUCCESS) + continue; + + if(port_name_length > 0 && port_name_length <= port_name_max_length) + port_name[port_name_length-1] = '\0'; + else + port_name[0] = '\0'; + + // Ignore parallel ports + + if(_tcsstr(port_name, _T("LPT")) != NULL) + continue; + + // Get port friendly name + + TCHAR friendly_name[friendly_name_max_length]; + DWORD friendly_name_actual_length = 0; + + BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty( + device_info_set, + &device_info_data, + SPDRP_FRIENDLYNAME, + NULL, + (PBYTE)friendly_name, + friendly_name_max_length, + &friendly_name_actual_length); + + if(got_friendly_name == TRUE && friendly_name_actual_length > 0) + friendly_name[friendly_name_actual_length-1] = '\0'; + else + friendly_name[0] = '\0'; + + // Get hardware ID + + TCHAR hardware_id[hardware_id_max_length]; + DWORD hardware_id_actual_length = 0; + + BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty( + device_info_set, + &device_info_data, + SPDRP_HARDWAREID, + NULL, + (PBYTE)hardware_id, + hardware_id_max_length, + &hardware_id_actual_length); + + if(got_hardware_id == TRUE && hardware_id_actual_length > 0) + hardware_id[hardware_id_actual_length-1] = '\0'; + else + hardware_id[0] = '\0'; + + #ifdef UNICODE + std::string portName = utf8_encode(port_name); + std::string friendlyName = utf8_encode(friendly_name); + std::string hardwareId = utf8_encode(hardware_id); + #else + std::string portName = port_name; + std::string friendlyName = friendly_name; + std::string hardwareId = hardware_id; + #endif + + PortInfo port_entry; + port_entry.port = portName; + port_entry.description = friendlyName; + port_entry.hardware_id = hardwareId; + + devices_found.push_back(port_entry); + } + + SetupDiDestroyDeviceInfoList(device_info_set); + + return devices_found; +} + +#endif // #if defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/src/impl/unix.cc b/code/c++/cxx-api/serial_support/src/impl/unix.cc new file mode 100644 index 0000000..4ef6b32 --- /dev/null +++ b/code/c++/cxx-api/serial_support/src/impl/unix.cc @@ -0,0 +1,1063 @@ +/* Copyright 2012 William Woodall and John Harrison + * + * Additional Contributors: Christopher Baker @bakercp + */ + +#if !defined(_WIN32) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +# include +#endif + +#include +#include +#include +#ifdef __MACH__ +#include +#include +#include +#endif + +#include "serial/impl/unix.h" + +#ifndef TIOCINQ +#ifdef FIONREAD +#define TIOCINQ FIONREAD +#else +#define TIOCINQ 0x541B +#endif +#endif + +#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3) +#include +#endif + +using std::string; +using std::stringstream; +using std::invalid_argument; +using serial::MillisecondTimer; +using serial::Serial; +using serial::SerialException; +using serial::PortNotOpenedException; +using serial::IOException; + + +MillisecondTimer::MillisecondTimer (const uint32_t millis) + : expiry(timespec_now()) +{ + int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6); + if (tv_nsec >= 1e9) { + int64_t sec_diff = tv_nsec / static_cast (1e9); + expiry.tv_nsec = tv_nsec % static_cast(1e9); + expiry.tv_sec += sec_diff; + } else { + expiry.tv_nsec = tv_nsec; + } +} + +int64_t +MillisecondTimer::remaining () +{ + timespec now(timespec_now()); + int64_t millis = (expiry.tv_sec - now.tv_sec) * 1e3; + millis += (expiry.tv_nsec - now.tv_nsec) / 1e6; + return millis; +} + +timespec +MillisecondTimer::timespec_now () +{ + timespec time; +# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + time.tv_sec = mts.tv_sec; + time.tv_nsec = mts.tv_nsec; +# else + clock_gettime(CLOCK_MONOTONIC, &time); +# endif + return time; +} + +timespec +timespec_from_ms (const uint32_t millis) +{ + timespec time; + time.tv_sec = millis / 1e3; + time.tv_nsec = (millis - (time.tv_sec * 1e3)) * 1e6; + return time; +} + +Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, + bytesize_t bytesize, + parity_t parity, stopbits_t stopbits, + flowcontrol_t flowcontrol) + : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (false), rtscts_ (false), + baudrate_ (baudrate), parity_ (parity), + bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) +{ + pthread_mutex_init(&this->read_mutex, NULL); + pthread_mutex_init(&this->write_mutex, NULL); + if (port_.empty () == false) + open (); +} + +Serial::SerialImpl::~SerialImpl () +{ + close(); + pthread_mutex_destroy(&this->read_mutex); + pthread_mutex_destroy(&this->write_mutex); +} + +void +Serial::SerialImpl::open () +{ + if (port_.empty ()) { + throw invalid_argument ("Empty port is invalid."); + } + if (is_open_ == true) { + throw SerialException ("Serial port already open."); + } + + fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); + + if (fd_ == -1) { + switch (errno) { + case EINTR: + // Recurse because this is a recoverable error. + open (); + return; + case ENFILE: + case EMFILE: + THROW (IOException, "Too many file handles open."); + default: + THROW (IOException, errno); + } + } + + reconfigurePort(); + is_open_ = true; +} + +void +Serial::SerialImpl::reconfigurePort () +{ + if (fd_ == -1) { + // Can only operate on a valid file descriptor + THROW (IOException, "Invalid file descriptor, is the serial port open?"); + } + + struct termios options; // The options for the file descriptor + + if (tcgetattr(fd_, &options) == -1) { + THROW (IOException, "::tcgetattr"); + } + + // set up raw mode / no echo / binary + options.c_cflag |= (tcflag_t) (CLOCAL | CREAD); + options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | + ISIG | IEXTEN); //|ECHOPRT + + options.c_oflag &= (tcflag_t) ~(OPOST); + options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK); +#ifdef IUCLC + options.c_iflag &= (tcflag_t) ~IUCLC; +#endif +#ifdef PARMRK + options.c_iflag &= (tcflag_t) ~PARMRK; +#endif + + // setup baud rate + bool custom_baud = false; + speed_t baud; + switch (baudrate_) { +#ifdef B0 + case 0: baud = B0; break; +#endif +#ifdef B50 + case 50: baud = B50; break; +#endif +#ifdef B75 + case 75: baud = B75; break; +#endif +#ifdef B110 + case 110: baud = B110; break; +#endif +#ifdef B134 + case 134: baud = B134; break; +#endif +#ifdef B150 + case 150: baud = B150; break; +#endif +#ifdef B200 + case 200: baud = B200; break; +#endif +#ifdef B300 + case 300: baud = B300; break; +#endif +#ifdef B600 + case 600: baud = B600; break; +#endif +#ifdef B1200 + case 1200: baud = B1200; break; +#endif +#ifdef B1800 + case 1800: baud = B1800; break; +#endif +#ifdef B2400 + case 2400: baud = B2400; break; +#endif +#ifdef B4800 + case 4800: baud = B4800; break; +#endif +#ifdef B7200 + case 7200: baud = B7200; break; +#endif +#ifdef B9600 + case 9600: baud = B9600; break; +#endif +#ifdef B14400 + case 14400: baud = B14400; break; +#endif +#ifdef B19200 + case 19200: baud = B19200; break; +#endif +#ifdef B28800 + case 28800: baud = B28800; break; +#endif +#ifdef B57600 + case 57600: baud = B57600; break; +#endif +#ifdef B76800 + case 76800: baud = B76800; break; +#endif +#ifdef B38400 + case 38400: baud = B38400; break; +#endif +#ifdef B115200 + case 115200: baud = B115200; break; +#endif +#ifdef B128000 + case 128000: baud = B128000; break; +#endif +#ifdef B153600 + case 153600: baud = B153600; break; +#endif +#ifdef B230400 + case 230400: baud = B230400; break; +#endif +#ifdef B256000 + case 256000: baud = B256000; break; +#endif +#ifdef B460800 + case 460800: baud = B460800; break; +#endif +#ifdef B576000 + case 576000: baud = B576000; break; +#endif +#ifdef B921600 + case 921600: baud = B921600; break; +#endif +#ifdef B1000000 + case 1000000: baud = B1000000; break; +#endif +#ifdef B1152000 + case 1152000: baud = B1152000; break; +#endif +#ifdef B1500000 + case 1500000: baud = B1500000; break; +#endif +#ifdef B2000000 + case 2000000: baud = B2000000; break; +#endif +#ifdef B2500000 + case 2500000: baud = B2500000; break; +#endif +#ifdef B3000000 + case 3000000: baud = B3000000; break; +#endif +#ifdef B3500000 + case 3500000: baud = B3500000; break; +#endif +#ifdef B4000000 + case 4000000: baud = B4000000; break; +#endif + default: + custom_baud = true; + // OS X support +#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) + // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates + // other than those specified by POSIX. The driver for the underlying serial hardware + // ultimately determines which baud rates can be used. This ioctl sets both the input + // and output speed. + speed_t new_baud = static_cast (baudrate_); + if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) { + THROW (IOException, errno); + } + // Linux Support +#elif defined(__linux__) && defined (TIOCSSERIAL) + struct serial_struct ser; + + if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) { + THROW (IOException, errno); + } + + // set custom divisor + ser.custom_divisor = ser.baud_base / static_cast (baudrate_); + // update flags + ser.flags &= ~ASYNC_SPD_MASK; + ser.flags |= ASYNC_SPD_CUST; + + if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) { + THROW (IOException, errno); + } +#else + throw invalid_argument ("OS does not currently support custom bauds"); +#endif + } + if (custom_baud == false) { +#ifdef _BSD_SOURCE + ::cfsetspeed(&options, baud); +#else + ::cfsetispeed(&options, baud); + ::cfsetospeed(&options, baud); +#endif + } + + // setup char len + options.c_cflag &= (tcflag_t) ~CSIZE; + if (bytesize_ == eightbits) + options.c_cflag |= CS8; + else if (bytesize_ == sevenbits) + options.c_cflag |= CS7; + else if (bytesize_ == sixbits) + options.c_cflag |= CS6; + else if (bytesize_ == fivebits) + options.c_cflag |= CS5; + else + throw invalid_argument ("invalid char len"); + // setup stopbits + if (stopbits_ == stopbits_one) + options.c_cflag &= (tcflag_t) ~(CSTOPB); + else if (stopbits_ == stopbits_one_point_five) + // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 + options.c_cflag |= (CSTOPB); + else if (stopbits_ == stopbits_two) + options.c_cflag |= (CSTOPB); + else + throw invalid_argument ("invalid stop bit"); + // setup parity + options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP); + if (parity_ == parity_none) { + options.c_cflag &= (tcflag_t) ~(PARENB | PARODD); + } else if (parity_ == parity_even) { + options.c_cflag &= (tcflag_t) ~(PARODD); + options.c_cflag |= (PARENB); + } else if (parity_ == parity_odd) { + options.c_cflag |= (PARENB | PARODD); + } +#ifdef CMSPAR + else if (parity_ == parity_mark) { + options.c_cflag |= (PARENB | CMSPAR | PARODD); + } + else if (parity_ == parity_space) { + options.c_cflag |= (PARENB | CMSPAR); + options.c_cflag &= (tcflag_t) ~(PARODD); + } +#else + // CMSPAR is not defined on OSX. So do not support mark or space parity. + else if (parity_ == parity_mark || parity_ == parity_space) { + throw invalid_argument ("OS does not support mark or space parity"); + } +#endif // ifdef CMSPAR + else { + throw invalid_argument ("invalid parity"); + } + // setup flow control + if (flowcontrol_ == flowcontrol_none) { + xonxoff_ = false; + rtscts_ = false; + } + if (flowcontrol_ == flowcontrol_software) { + xonxoff_ = true; + rtscts_ = false; + } + if (flowcontrol_ == flowcontrol_hardware) { + xonxoff_ = false; + rtscts_ = true; + } + // xonxoff +#ifdef IXANY + if (xonxoff_) + options.c_iflag |= (IXON | IXOFF); //|IXANY) + else + options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY); +#else + if (xonxoff_) + options.c_iflag |= (IXON | IXOFF); + else + options.c_iflag &= (tcflag_t) ~(IXON | IXOFF); +#endif + // rtscts +#ifdef CRTSCTS + if (rtscts_) + options.c_cflag |= (CRTSCTS); + else + options.c_cflag &= (unsigned long) ~(CRTSCTS); +#elif defined CNEW_RTSCTS + if (rtscts_) + options.c_cflag |= (CNEW_RTSCTS); + else + options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS); +#else +#error "OS Support seems wrong." +#endif + + // http://www.unixwiz.net/techtips/termios-vmin-vtime.html + // this basically sets the read call up to be a polling read, + // but we are using select to ensure there is data available + // to read before each call, so we should never needlessly poll + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 0; + + // activate settings + ::tcsetattr (fd_, TCSANOW, &options); + + // Update byte_time_ based on the new settings. + uint32_t bit_time_ns = 1e9 / baudrate_; + byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_); + + // Compensate for the stopbits_one_point_five enum being equal to int 3, + // and not 1.5. + if (stopbits_ == stopbits_one_point_five) { + byte_time_ns_ += ((1.5 - stopbits_one_point_five) * bit_time_ns); + } +} + +void +Serial::SerialImpl::close () +{ + if (is_open_ == true) { + if (fd_ != -1) { + int ret; + ret = ::close (fd_); + if (ret == 0) { + fd_ = -1; + } else { + THROW (IOException, errno); + } + } + is_open_ = false; + } +} + +bool +Serial::SerialImpl::isOpen () const +{ + return is_open_; +} + +size_t +Serial::SerialImpl::available () +{ + if (!is_open_) { + return 0; + } + int count = 0; + if (-1 == ioctl (fd_, TIOCINQ, &count)) { + THROW (IOException, errno); + } else { + return static_cast (count); + } +} + +bool +Serial::SerialImpl::waitReadable (uint32_t timeout) +{ + // Setup a select call to block for serial data or a timeout + fd_set readfds; + FD_ZERO (&readfds); + FD_SET (fd_, &readfds); + timespec timeout_ts (timespec_from_ms (timeout)); + int r = pselect (fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL); + + if (r < 0) { + // Select was interrupted + if (errno == EINTR) { + return false; + } + // Otherwise there was some error + THROW (IOException, errno); + } + // Timeout occurred + if (r == 0) { + return false; + } + // This shouldn't happen, if r > 0 our fd has to be in the list! + if (!FD_ISSET (fd_, &readfds)) { + THROW (IOException, "select reports ready to read, but our fd isn't" + " in the list, this shouldn't happen!"); + } + // Data available to read. + return true; +} + +void +Serial::SerialImpl::waitByteTimes (size_t count) +{ + timespec wait_time = { 0, static_cast(byte_time_ns_ * count)}; + pselect (0, NULL, NULL, NULL, &wait_time, NULL); +} + +size_t +Serial::SerialImpl::read (uint8_t *buf, size_t size) +{ + // If the port is not open, throw + if (!is_open_) { + throw PortNotOpenedException ("Serial::read"); + } + size_t bytes_read = 0; + + // Calculate total timeout in milliseconds t_c + (t_m * N) + long total_timeout_ms = timeout_.read_timeout_constant; + total_timeout_ms += timeout_.read_timeout_multiplier * static_cast (size); + MillisecondTimer total_timeout(total_timeout_ms); + + // Pre-fill buffer with available bytes + { + ssize_t bytes_read_now = ::read (fd_, buf, size); + if (bytes_read_now > 0) { + bytes_read = bytes_read_now; + } + } + + while (bytes_read < size) { + int64_t timeout_remaining_ms = total_timeout.remaining(); + if (timeout_remaining_ms <= 0) { + // Timed out + break; + } + // Timeout for the next select is whichever is less of the remaining + // total read timeout and the inter-byte timeout. + uint32_t timeout = std::min(static_cast (timeout_remaining_ms), + timeout_.inter_byte_timeout); + // Wait for the device to be readable, and then attempt to read. + if (waitReadable(timeout)) { + // If it's a fixed-length multi-byte read, insert a wait here so that + // we can attempt to grab the whole thing in a single IO call. Skip + // this wait if a non-max inter_byte_timeout is specified. + if (size > 1 && timeout_.inter_byte_timeout == Timeout::max()) { + size_t bytes_available = available(); + if (bytes_available + bytes_read < size) { + waitByteTimes(size - (bytes_available + bytes_read)); + } + } + // This should be non-blocking returning only what is available now + // Then returning so that select can block again. + ssize_t bytes_read_now = + ::read (fd_, buf + bytes_read, size - bytes_read); + // read should always return some data as select reported it was + // ready to read when we get to this point. + if (bytes_read_now < 1) { + // Disconnected devices, at least on Linux, show the + // behavior that they are always ready to read immediately + // but reading returns nothing. + throw SerialException ("device reports readiness to read but " + "returned no data (device disconnected?)"); + } + // Update bytes_read + bytes_read += static_cast (bytes_read_now); + // If bytes_read == size then we have read everything we need + if (bytes_read == size) { + break; + } + // If bytes_read < size then we have more to read + if (bytes_read < size) { + continue; + } + // If bytes_read > size then we have over read, which shouldn't happen + if (bytes_read > size) { + throw SerialException ("read over read, too many bytes where " + "read, this shouldn't happen, might be " + "a logical error!"); + } + } + } + return bytes_read; +} + +size_t +Serial::SerialImpl::write (const uint8_t *data, size_t length) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::write"); + } + fd_set writefds; + size_t bytes_written = 0; + + // Calculate total timeout in milliseconds t_c + (t_m * N) + long total_timeout_ms = timeout_.write_timeout_constant; + total_timeout_ms += timeout_.write_timeout_multiplier * static_cast (length); + MillisecondTimer total_timeout(total_timeout_ms); + + bool first_iteration = true; + while (bytes_written < length) { + int64_t timeout_remaining_ms = total_timeout.remaining(); + // Only consider the timeout if it's not the first iteration of the loop + // otherwise a timeout of 0 won't be allowed through + if (!first_iteration && (timeout_remaining_ms <= 0)) { + // Timed out + break; + } + first_iteration = false; + + timespec timeout(timespec_from_ms(timeout_remaining_ms)); + + FD_ZERO (&writefds); + FD_SET (fd_, &writefds); + + // Do the select + int r = pselect (fd_ + 1, NULL, &writefds, NULL, &timeout, NULL); + + // Figure out what happened by looking at select's response 'r' + /** Error **/ + if (r < 0) { + // Select was interrupted, try again + if (errno == EINTR) { + continue; + } + // Otherwise there was some error + THROW (IOException, errno); + } + /** Timeout **/ + if (r == 0) { + break; + } + /** Port ready to write **/ + if (r > 0) { + // Make sure our file descriptor is in the ready to write list + if (FD_ISSET (fd_, &writefds)) { + // This will write some + ssize_t bytes_written_now = + ::write (fd_, data + bytes_written, length - bytes_written); + // write should always return some data as select reported it was + // ready to write when we get to this point. + if (bytes_written_now < 1) { + // Disconnected devices, at least on Linux, show the + // behavior that they are always ready to write immediately + // but writing returns nothing. + throw SerialException ("device reports readiness to write but " + "returned no data (device disconnected?)"); + } + // Update bytes_written + bytes_written += static_cast (bytes_written_now); + // If bytes_written == size then we have written everything we need to + if (bytes_written == length) { + break; + } + // If bytes_written < size then we have more to write + if (bytes_written < length) { + continue; + } + // If bytes_written > size then we have over written, which shouldn't happen + if (bytes_written > length) { + throw SerialException ("write over wrote, too many bytes where " + "written, this shouldn't happen, might be " + "a logical error!"); + } + } + // This shouldn't happen, if r > 0 our fd has to be in the list! + THROW (IOException, "select reports ready to write, but our fd isn't" + " in the list, this shouldn't happen!"); + } + } + return bytes_written; +} + +void +Serial::SerialImpl::setPort (const string &port) +{ + port_ = port; +} + +string +Serial::SerialImpl::getPort () const +{ + return port_; +} + +void +Serial::SerialImpl::setTimeout (serial::Timeout &timeout) +{ + timeout_ = timeout; +} + +serial::Timeout +Serial::SerialImpl::getTimeout () const +{ + return timeout_; +} + +void +Serial::SerialImpl::setBaudrate (unsigned long baudrate) +{ + baudrate_ = baudrate; + if (is_open_) + reconfigurePort (); +} + +unsigned long +Serial::SerialImpl::getBaudrate () const +{ + return baudrate_; +} + +void +Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) +{ + bytesize_ = bytesize; + if (is_open_) + reconfigurePort (); +} + +serial::bytesize_t +Serial::SerialImpl::getBytesize () const +{ + return bytesize_; +} + +void +Serial::SerialImpl::setParity (serial::parity_t parity) +{ + parity_ = parity; + if (is_open_) + reconfigurePort (); +} + +serial::parity_t +Serial::SerialImpl::getParity () const +{ + return parity_; +} + +void +Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) +{ + stopbits_ = stopbits; + if (is_open_) + reconfigurePort (); +} + +serial::stopbits_t +Serial::SerialImpl::getStopbits () const +{ + return stopbits_; +} + +void +Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) +{ + flowcontrol_ = flowcontrol; + if (is_open_) + reconfigurePort (); +} + +serial::flowcontrol_t +Serial::SerialImpl::getFlowcontrol () const +{ + return flowcontrol_; +} + +void +Serial::SerialImpl::flush () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::flush"); + } + tcdrain (fd_); +} + +void +Serial::SerialImpl::flushInput () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::flushInput"); + } + tcflush (fd_, TCIFLUSH); +} + +void +Serial::SerialImpl::flushOutput () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::flushOutput"); + } + tcflush (fd_, TCOFLUSH); +} + +void +Serial::SerialImpl::sendBreak (int duration) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::sendBreak"); + } + tcsendbreak (fd_, static_cast (duration / 4)); +} + +void +Serial::SerialImpl::setBreak (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setBreak"); + } + + if (level) { + if (-1 == ioctl (fd_, TIOCSBRK)) + { + stringstream ss; + ss << "setBreak failed on a call to ioctl(TIOCSBRK): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + } else { + if (-1 == ioctl (fd_, TIOCCBRK)) + { + stringstream ss; + ss << "setBreak failed on a call to ioctl(TIOCCBRK): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + } +} + +void +Serial::SerialImpl::setRTS (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setRTS"); + } + + int command = TIOCM_RTS; + + if (level) { + if (-1 == ioctl (fd_, TIOCMBIS, &command)) + { + stringstream ss; + ss << "setRTS failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + } else { + if (-1 == ioctl (fd_, TIOCMBIC, &command)) + { + stringstream ss; + ss << "setRTS failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + } +} + +void +Serial::SerialImpl::setDTR (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setDTR"); + } + + int command = TIOCM_DTR; + + if (level) { + if (-1 == ioctl (fd_, TIOCMBIS, &command)) + { + stringstream ss; + ss << "setDTR failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + } else { + if (-1 == ioctl (fd_, TIOCMBIC, &command)) + { + stringstream ss; + ss << "setDTR failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + } +} + +bool +Serial::SerialImpl::waitForChange () +{ +#ifndef TIOCMIWAIT + +while (is_open_ == true) { + + int status; + + if (-1 == ioctl (fd_, TIOCMGET, &status)) + { + stringstream ss; + ss << "waitForChange failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + else + { + if (0 != (status & TIOCM_CTS) + || 0 != (status & TIOCM_DSR) + || 0 != (status & TIOCM_RI) + || 0 != (status & TIOCM_CD)) + { + return true; + } + } + + usleep(1000); + } + + return false; +#else + int command = (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS); + + if (-1 == ioctl (fd_, TIOCMIWAIT, &command)) { + stringstream ss; + ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): " + << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + return true; +#endif +} + +bool +Serial::SerialImpl::getCTS () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getCTS"); + } + + int status; + + if (-1 == ioctl (fd_, TIOCMGET, &status)) + { + stringstream ss; + ss << "getCTS failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + else + { + return 0 != (status & TIOCM_CTS); + } +} + +bool +Serial::SerialImpl::getDSR () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getDSR"); + } + + int status; + + if (-1 == ioctl (fd_, TIOCMGET, &status)) + { + stringstream ss; + ss << "getDSR failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + else + { + return 0 != (status & TIOCM_DSR); + } +} + +bool +Serial::SerialImpl::getRI () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getRI"); + } + + int status; + + if (-1 == ioctl (fd_, TIOCMGET, &status)) + { + stringstream ss; + ss << "getRI failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + else + { + return 0 != (status & TIOCM_RI); + } +} + +bool +Serial::SerialImpl::getCD () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getCD"); + } + + int status; + + if (-1 == ioctl (fd_, TIOCMGET, &status)) + { + stringstream ss; + ss << "getCD failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); + throw(SerialException(ss.str().c_str())); + } + else + { + return 0 != (status & TIOCM_CD); + } +} + +void +Serial::SerialImpl::readLock () +{ + int result = pthread_mutex_lock(&this->read_mutex); + if (result) { + THROW (IOException, result); + } +} + +void +Serial::SerialImpl::readUnlock () +{ + int result = pthread_mutex_unlock(&this->read_mutex); + if (result) { + THROW (IOException, result); + } +} + +void +Serial::SerialImpl::writeLock () +{ + int result = pthread_mutex_lock(&this->write_mutex); + if (result) { + THROW (IOException, result); + } +} + +void +Serial::SerialImpl::writeUnlock () +{ + int result = pthread_mutex_unlock(&this->write_mutex); + if (result) { + THROW (IOException, result); + } +} + +#endif // !defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/src/impl/win.cc b/code/c++/cxx-api/serial_support/src/impl/win.cc new file mode 100644 index 0000000..3446160 --- /dev/null +++ b/code/c++/cxx-api/serial_support/src/impl/win.cc @@ -0,0 +1,640 @@ +#if defined(_WIN32) + +/* Copyright 2012 William Woodall and John Harrison */ + +#include + +#include "serial/impl/win.h" + +using std::string; +using std::wstring; +using std::stringstream; +using std::invalid_argument; +using serial::Serial; +using serial::Timeout; +using serial::bytesize_t; +using serial::parity_t; +using serial::stopbits_t; +using serial::flowcontrol_t; +using serial::SerialException; +using serial::PortNotOpenedException; +using serial::IOException; + +inline wstring +_prefix_port_if_needed(const wstring &input) +{ + static wstring windows_com_port_prefix = L"\\\\.\\"; + if (input.compare(windows_com_port_prefix) != 0) + { + return windows_com_port_prefix + input; + } + return input; +} + +Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, + bytesize_t bytesize, + parity_t parity, stopbits_t stopbits, + flowcontrol_t flowcontrol) + : port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false), + baudrate_ (baudrate), parity_ (parity), + bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) +{ + if (port_.empty () == false) + open (); + read_mutex = CreateMutex(NULL, false, NULL); + write_mutex = CreateMutex(NULL, false, NULL); +} + +Serial::SerialImpl::~SerialImpl () +{ + this->close(); + CloseHandle(read_mutex); + CloseHandle(write_mutex); +} + +void +Serial::SerialImpl::open () +{ + if (port_.empty ()) { + throw invalid_argument ("Empty port is invalid."); + } + if (is_open_ == true) { + throw SerialException ("Serial port already open."); + } + + // See: https://github.com/wjwwood/serial/issues/84 + wstring port_with_prefix = _prefix_port_if_needed(port_); + LPCWSTR lp_port = port_with_prefix.c_str(); + fd_ = CreateFileW(lp_port, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); + + if (fd_ == INVALID_HANDLE_VALUE) { + DWORD errno_ = GetLastError(); + stringstream ss; + switch (errno_) { + case ERROR_FILE_NOT_FOUND: + // Use this->getPort to convert to a std::string + ss << "Specified port, " << this->getPort() << ", does not exist."; + THROW (IOException, ss.str().c_str()); + default: + ss << "Unknown error opening the serial port: " << errno; + THROW (IOException, ss.str().c_str()); + } + } + + reconfigurePort(); + is_open_ = true; +} + +void +Serial::SerialImpl::reconfigurePort () +{ + if (fd_ == INVALID_HANDLE_VALUE) { + // Can only operate on a valid file descriptor + THROW (IOException, "Invalid file descriptor, is the serial port open?"); + } + + DCB dcbSerialParams = {0}; + + dcbSerialParams.DCBlength=sizeof(dcbSerialParams); + + if (!GetCommState(fd_, &dcbSerialParams)) { + //error getting state + THROW (IOException, "Error getting the serial port state."); + } + + // setup baud rate + switch (baudrate_) { +#ifdef CBR_0 + case 0: dcbSerialParams.BaudRate = CBR_0; break; +#endif +#ifdef CBR_50 + case 50: dcbSerialParams.BaudRate = CBR_50; break; +#endif +#ifdef CBR_75 + case 75: dcbSerialParams.BaudRate = CBR_75; break; +#endif +#ifdef CBR_110 + case 110: dcbSerialParams.BaudRate = CBR_110; break; +#endif +#ifdef CBR_134 + case 134: dcbSerialParams.BaudRate = CBR_134; break; +#endif +#ifdef CBR_150 + case 150: dcbSerialParams.BaudRate = CBR_150; break; +#endif +#ifdef CBR_200 + case 200: dcbSerialParams.BaudRate = CBR_200; break; +#endif +#ifdef CBR_300 + case 300: dcbSerialParams.BaudRate = CBR_300; break; +#endif +#ifdef CBR_600 + case 600: dcbSerialParams.BaudRate = CBR_600; break; +#endif +#ifdef CBR_1200 + case 1200: dcbSerialParams.BaudRate = CBR_1200; break; +#endif +#ifdef CBR_1800 + case 1800: dcbSerialParams.BaudRate = CBR_1800; break; +#endif +#ifdef CBR_2400 + case 2400: dcbSerialParams.BaudRate = CBR_2400; break; +#endif +#ifdef CBR_4800 + case 4800: dcbSerialParams.BaudRate = CBR_4800; break; +#endif +#ifdef CBR_7200 + case 7200: dcbSerialParams.BaudRate = CBR_7200; break; +#endif +#ifdef CBR_9600 + case 9600: dcbSerialParams.BaudRate = CBR_9600; break; +#endif +#ifdef CBR_14400 + case 14400: dcbSerialParams.BaudRate = CBR_14400; break; +#endif +#ifdef CBR_19200 + case 19200: dcbSerialParams.BaudRate = CBR_19200; break; +#endif +#ifdef CBR_28800 + case 28800: dcbSerialParams.BaudRate = CBR_28800; break; +#endif +#ifdef CBR_57600 + case 57600: dcbSerialParams.BaudRate = CBR_57600; break; +#endif +#ifdef CBR_76800 + case 76800: dcbSerialParams.BaudRate = CBR_76800; break; +#endif +#ifdef CBR_38400 + case 38400: dcbSerialParams.BaudRate = CBR_38400; break; +#endif +#ifdef CBR_115200 + case 115200: dcbSerialParams.BaudRate = CBR_115200; break; +#endif +#ifdef CBR_128000 + case 128000: dcbSerialParams.BaudRate = CBR_128000; break; +#endif +#ifdef CBR_153600 + case 153600: dcbSerialParams.BaudRate = CBR_153600; break; +#endif +#ifdef CBR_230400 + case 230400: dcbSerialParams.BaudRate = CBR_230400; break; +#endif +#ifdef CBR_256000 + case 256000: dcbSerialParams.BaudRate = CBR_256000; break; +#endif +#ifdef CBR_460800 + case 460800: dcbSerialParams.BaudRate = CBR_460800; break; +#endif +#ifdef CBR_921600 + case 921600: dcbSerialParams.BaudRate = CBR_921600; break; +#endif + default: + // Try to blindly assign it + dcbSerialParams.BaudRate = baudrate_; + } + + // setup char len + if (bytesize_ == eightbits) + dcbSerialParams.ByteSize = 8; + else if (bytesize_ == sevenbits) + dcbSerialParams.ByteSize = 7; + else if (bytesize_ == sixbits) + dcbSerialParams.ByteSize = 6; + else if (bytesize_ == fivebits) + dcbSerialParams.ByteSize = 5; + else + throw invalid_argument ("invalid char len"); + + // setup stopbits + if (stopbits_ == stopbits_one) + dcbSerialParams.StopBits = ONESTOPBIT; + else if (stopbits_ == stopbits_one_point_five) + dcbSerialParams.StopBits = ONE5STOPBITS; + else if (stopbits_ == stopbits_two) + dcbSerialParams.StopBits = TWOSTOPBITS; + else + throw invalid_argument ("invalid stop bit"); + + // setup parity + if (parity_ == parity_none) { + dcbSerialParams.Parity = NOPARITY; + } else if (parity_ == parity_even) { + dcbSerialParams.Parity = EVENPARITY; + } else if (parity_ == parity_odd) { + dcbSerialParams.Parity = ODDPARITY; + } else if (parity_ == parity_mark) { + dcbSerialParams.Parity = MARKPARITY; + } else if (parity_ == parity_space) { + dcbSerialParams.Parity = SPACEPARITY; + } else { + throw invalid_argument ("invalid parity"); + } + + // setup flowcontrol + if (flowcontrol_ == flowcontrol_none) { + dcbSerialParams.fOutxCtsFlow = false; + dcbSerialParams.fRtsControl = 0x00; + dcbSerialParams.fOutX = false; + dcbSerialParams.fInX = false; + } + if (flowcontrol_ == flowcontrol_software) { + dcbSerialParams.fOutxCtsFlow = false; + dcbSerialParams.fRtsControl = 0x00; + dcbSerialParams.fOutX = true; + dcbSerialParams.fInX = true; + } + if (flowcontrol_ == flowcontrol_hardware) { + dcbSerialParams.fOutxCtsFlow = true; + dcbSerialParams.fRtsControl = 0x03; + dcbSerialParams.fOutX = false; + dcbSerialParams.fInX = false; + } + + // activate settings + if (!SetCommState(fd_, &dcbSerialParams)){ + CloseHandle(fd_); + THROW (IOException, "Error setting serial port settings."); + } + + // Setup timeouts + COMMTIMEOUTS timeouts = {0}; + timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout; + timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant; + timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier; + timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant; + timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier; + if (!SetCommTimeouts(fd_, &timeouts)) { + THROW (IOException, "Error setting timeouts."); + } +} + +void +Serial::SerialImpl::close () +{ + if (is_open_ == true) { + if (fd_ != INVALID_HANDLE_VALUE) { + int ret; + ret = CloseHandle(fd_); + if (ret == 0) { + stringstream ss; + ss << "Error while closing serial port: " << GetLastError(); + THROW (IOException, ss.str().c_str()); + } else { + fd_ = INVALID_HANDLE_VALUE; + } + } + is_open_ = false; + } +} + +bool +Serial::SerialImpl::isOpen () const +{ + return is_open_; +} + +size_t +Serial::SerialImpl::available () +{ + if (!is_open_) { + return 0; + } + COMSTAT cs; + if (!ClearCommError(fd_, NULL, &cs)) { + stringstream ss; + ss << "Error while checking status of the serial port: " << GetLastError(); + THROW (IOException, ss.str().c_str()); + } + return static_cast(cs.cbInQue); +} + +bool +Serial::SerialImpl::waitReadable (uint32_t /*timeout*/) +{ + THROW (IOException, "waitReadable is not implemented on Windows."); + return false; +} + +void +Serial::SerialImpl::waitByteTimes (size_t /*count*/) +{ + THROW (IOException, "waitByteTimes is not implemented on Windows."); +} + +size_t +Serial::SerialImpl::read (uint8_t *buf, size_t size) +{ + if (!is_open_) { + throw PortNotOpenedException ("Serial::read"); + } + DWORD bytes_read; + if (!ReadFile(fd_, buf, static_cast(size), &bytes_read, NULL)) { + stringstream ss; + ss << "Error while reading from the serial port: " << GetLastError(); + THROW (IOException, ss.str().c_str()); + } + return (size_t) (bytes_read); +} + +size_t +Serial::SerialImpl::write (const uint8_t *data, size_t length) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::write"); + } + DWORD bytes_written; + if (!WriteFile(fd_, data, static_cast(length), &bytes_written, NULL)) { + stringstream ss; + ss << "Error while writing to the serial port: " << GetLastError(); + THROW (IOException, ss.str().c_str()); + } + return (size_t) (bytes_written); +} + +void +Serial::SerialImpl::setPort (const string &port) +{ + port_ = wstring(port.begin(), port.end()); +} + +string +Serial::SerialImpl::getPort () const +{ + return string(port_.begin(), port_.end()); +} + +void +Serial::SerialImpl::setTimeout (serial::Timeout &timeout) +{ + timeout_ = timeout; + if (is_open_) { + reconfigurePort (); + } +} + +serial::Timeout +Serial::SerialImpl::getTimeout () const +{ + return timeout_; +} + +void +Serial::SerialImpl::setBaudrate (unsigned long baudrate) +{ + baudrate_ = baudrate; + if (is_open_) { + reconfigurePort (); + } +} + +unsigned long +Serial::SerialImpl::getBaudrate () const +{ + return baudrate_; +} + +void +Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) +{ + bytesize_ = bytesize; + if (is_open_) { + reconfigurePort (); + } +} + +serial::bytesize_t +Serial::SerialImpl::getBytesize () const +{ + return bytesize_; +} + +void +Serial::SerialImpl::setParity (serial::parity_t parity) +{ + parity_ = parity; + if (is_open_) { + reconfigurePort (); + } +} + +serial::parity_t +Serial::SerialImpl::getParity () const +{ + return parity_; +} + +void +Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) +{ + stopbits_ = stopbits; + if (is_open_) { + reconfigurePort (); + } +} + +serial::stopbits_t +Serial::SerialImpl::getStopbits () const +{ + return stopbits_; +} + +void +Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) +{ + flowcontrol_ = flowcontrol; + if (is_open_) { + reconfigurePort (); + } +} + +serial::flowcontrol_t +Serial::SerialImpl::getFlowcontrol () const +{ + return flowcontrol_; +} + +void +Serial::SerialImpl::flush () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::flush"); + } + FlushFileBuffers (fd_); +} + +void +Serial::SerialImpl::flushInput () +{ + THROW (IOException, "flushInput is not supported on Windows."); +} + +void +Serial::SerialImpl::flushOutput () +{ + THROW (IOException, "flushOutput is not supported on Windows."); +} + +void +Serial::SerialImpl::sendBreak (int /*duration*/) +{ + THROW (IOException, "sendBreak is not supported on Windows."); +} + +void +Serial::SerialImpl::setBreak (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setBreak"); + } + if (level) { + EscapeCommFunction (fd_, SETBREAK); + } else { + EscapeCommFunction (fd_, CLRBREAK); + } +} + +void +Serial::SerialImpl::setRTS (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setRTS"); + } + if (level) { + EscapeCommFunction (fd_, SETRTS); + } else { + EscapeCommFunction (fd_, CLRRTS); + } +} + +void +Serial::SerialImpl::setDTR (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setDTR"); + } + if (level) { + EscapeCommFunction (fd_, SETDTR); + } else { + EscapeCommFunction (fd_, CLRDTR); + } +} + +bool +Serial::SerialImpl::waitForChange () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::waitForChange"); + } + DWORD dwCommEvent; + + if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) { + // Error setting communications mask + return false; + } + + if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) { + // An error occurred waiting for the event. + return false; + } else { + // Event has occurred. + return true; + } +} + +bool +Serial::SerialImpl::getCTS () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getCTS"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) { + THROW (IOException, "Error getting the status of the CTS line."); + } + + return (MS_CTS_ON & dwModemStatus) != 0; +} + +bool +Serial::SerialImpl::getDSR () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getDSR"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) { + THROW (IOException, "Error getting the status of the DSR line."); + } + + return (MS_DSR_ON & dwModemStatus) != 0; +} + +bool +Serial::SerialImpl::getRI() +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getRI"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) { + THROW (IOException, "Error getting the status of the RI line."); + } + + return (MS_RING_ON & dwModemStatus) != 0; +} + +bool +Serial::SerialImpl::getCD() +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getCD"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) { + // Error in GetCommModemStatus; + THROW (IOException, "Error getting the status of the CD line."); + } + + return (MS_RLSD_ON & dwModemStatus) != 0; +} + +void +Serial::SerialImpl::readLock() +{ + if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) { + THROW (IOException, "Error claiming read mutex."); + } +} + +void +Serial::SerialImpl::readUnlock() +{ + if (!ReleaseMutex(read_mutex)) { + THROW (IOException, "Error releasing read mutex."); + } +} + +void +Serial::SerialImpl::writeLock() +{ + if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) { + THROW (IOException, "Error claiming write mutex."); + } +} + +void +Serial::SerialImpl::writeUnlock() +{ + if (!ReleaseMutex(write_mutex)) { + THROW (IOException, "Error releasing write mutex."); + } +} + +#endif // #if defined(_WIN32) + diff --git a/code/c++/cxx-api/serial_support/src/serial.cc b/code/c++/cxx-api/serial_support/src/serial.cc new file mode 100644 index 0000000..aab4caa --- /dev/null +++ b/code/c++/cxx-api/serial_support/src/serial.cc @@ -0,0 +1,414 @@ +/* Copyright 2012 William Woodall and John Harrison */ +#include + +#if !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__) +# include +#endif + +#if defined (__MINGW32__) +# define alloca __builtin_alloca +#endif + +#include "serial/serial.h" + +#ifdef _WIN32 +#include "serial/impl/win.h" +#else +#include "serial/impl/unix.h" +#endif + +using std::invalid_argument; +using std::min; +using std::numeric_limits; +using std::vector; +using std::size_t; +using std::string; + +using serial::Serial; +using serial::SerialException; +using serial::IOException; +using serial::bytesize_t; +using serial::parity_t; +using serial::stopbits_t; +using serial::flowcontrol_t; + +class Serial::ScopedReadLock { +public: + ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) { + this->pimpl_->readLock(); + } + ~ScopedReadLock() { + this->pimpl_->readUnlock(); + } +private: + // Disable copy constructors + ScopedReadLock(const ScopedReadLock&); + const ScopedReadLock& operator=(ScopedReadLock); + + SerialImpl *pimpl_; +}; + +class Serial::ScopedWriteLock { +public: + ScopedWriteLock(SerialImpl *pimpl) : pimpl_(pimpl) { + this->pimpl_->writeLock(); + } + ~ScopedWriteLock() { + this->pimpl_->writeUnlock(); + } +private: + // Disable copy constructors + ScopedWriteLock(const ScopedWriteLock&); + const ScopedWriteLock& operator=(ScopedWriteLock); + SerialImpl *pimpl_; +}; + +Serial::Serial (const string &port, uint32_t baudrate, serial::Timeout timeout, + bytesize_t bytesize, parity_t parity, stopbits_t stopbits, + flowcontrol_t flowcontrol) + : pimpl_(new SerialImpl (port, baudrate, bytesize, parity, + stopbits, flowcontrol)) +{ + pimpl_->setTimeout(timeout); +} + +Serial::~Serial () +{ + delete pimpl_; +} + +void +Serial::open () +{ + pimpl_->open (); +} + +void +Serial::close () +{ + pimpl_->close (); +} + +bool +Serial::isOpen () const +{ + return pimpl_->isOpen (); +} + +size_t +Serial::available () +{ + return pimpl_->available (); +} + +bool +Serial::waitReadable () +{ + serial::Timeout timeout(pimpl_->getTimeout ()); + return pimpl_->waitReadable(timeout.read_timeout_constant); +} + +void +Serial::waitByteTimes (size_t count) +{ + pimpl_->waitByteTimes(count); +} + +size_t +Serial::read_ (uint8_t *buffer, size_t size) +{ + return this->pimpl_->read (buffer, size); +} + +size_t +Serial::read (uint8_t *buffer, size_t size) +{ + ScopedReadLock lock(this->pimpl_); + return this->pimpl_->read (buffer, size); +} + +size_t +Serial::read (std::vector &buffer, size_t size) +{ + ScopedReadLock lock(this->pimpl_); + uint8_t *buffer_ = new uint8_t[size]; + size_t bytes_read = this->pimpl_->read (buffer_, size); + buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); + delete[] buffer_; + return bytes_read; +} + +size_t +Serial::read (std::string &buffer, size_t size) +{ + ScopedReadLock lock(this->pimpl_); + uint8_t *buffer_ = new uint8_t[size]; + size_t bytes_read = this->pimpl_->read (buffer_, size); + buffer.append (reinterpret_cast(buffer_), bytes_read); + delete[] buffer_; + return bytes_read; +} + +string +Serial::read (size_t size) +{ + std::string buffer; + this->read (buffer, size); + return buffer; +} + +size_t +Serial::readline (string &buffer, size_t size, string eol) +{ + ScopedReadLock lock(this->pimpl_); + size_t eol_len = eol.length (); + uint8_t *buffer_ = static_cast + (alloca (size * sizeof (uint8_t))); + size_t read_so_far = 0; + while (true) + { + size_t bytes_read = this->read_ (buffer_ + read_so_far, 1); + read_so_far += bytes_read; + if (bytes_read == 0) { + break; // Timeout occured on reading 1 byte + } + if (string (reinterpret_cast + (buffer_ + read_so_far - eol_len), eol_len) == eol) { + break; // EOL found + } + if (read_so_far == size) { + break; // Reached the maximum read length + } + } + buffer.append(reinterpret_cast (buffer_), read_so_far); + return read_so_far; +} + +string +Serial::readline (size_t size, string eol) +{ + std::string buffer; + this->readline (buffer, size, eol); + return buffer; +} + +vector +Serial::readlines (size_t size, string eol) +{ + ScopedReadLock lock(this->pimpl_); + std::vector lines; + size_t eol_len = eol.length (); + uint8_t *buffer_ = static_cast + (alloca (size * sizeof (uint8_t))); + size_t read_so_far = 0; + size_t start_of_line = 0; + while (read_so_far < size) { + size_t bytes_read = this->read_ (buffer_+read_so_far, 1); + read_so_far += bytes_read; + if (bytes_read == 0) { + if (start_of_line != read_so_far) { + lines.push_back ( + string (reinterpret_cast (buffer_ + start_of_line), + read_so_far - start_of_line)); + } + break; // Timeout occured on reading 1 byte + } + if (string (reinterpret_cast + (buffer_ + read_so_far - eol_len), eol_len) == eol) { + // EOL found + lines.push_back( + string(reinterpret_cast (buffer_ + start_of_line), + read_so_far - start_of_line)); + start_of_line = read_so_far; + } + if (read_so_far == size) { + if (start_of_line != read_so_far) { + lines.push_back( + string(reinterpret_cast (buffer_ + start_of_line), + read_so_far - start_of_line)); + } + break; // Reached the maximum read length + } + } + return lines; +} + +size_t +Serial::write (const string &data) +{ + ScopedWriteLock lock(this->pimpl_); + return this->write_ (reinterpret_cast(data.c_str()), + data.length()); +} + +size_t +Serial::write (const std::vector &data) +{ + ScopedWriteLock lock(this->pimpl_); + return this->write_ (&data[0], data.size()); +} + +size_t +Serial::write (const uint8_t *data, size_t size) +{ + ScopedWriteLock lock(this->pimpl_); + return this->write_(data, size); +} + +size_t +Serial::write_ (const uint8_t *data, size_t length) +{ + return pimpl_->write (data, length); +} + +void +Serial::setPort (const string &port) +{ + ScopedReadLock rlock(this->pimpl_); + ScopedWriteLock wlock(this->pimpl_); + bool was_open = pimpl_->isOpen (); + if (was_open) close(); + pimpl_->setPort (port); + if (was_open) open (); +} + +string +Serial::getPort () const +{ + return pimpl_->getPort (); +} + +void +Serial::setTimeout (serial::Timeout &timeout) +{ + pimpl_->setTimeout (timeout); +} + +serial::Timeout +Serial::getTimeout () const { + return pimpl_->getTimeout (); +} + +void +Serial::setBaudrate (uint32_t baudrate) +{ + pimpl_->setBaudrate (baudrate); +} + +uint32_t +Serial::getBaudrate () const +{ + return uint32_t(pimpl_->getBaudrate ()); +} + +void +Serial::setBytesize (bytesize_t bytesize) +{ + pimpl_->setBytesize (bytesize); +} + +bytesize_t +Serial::getBytesize () const +{ + return pimpl_->getBytesize (); +} + +void +Serial::setParity (parity_t parity) +{ + pimpl_->setParity (parity); +} + +parity_t +Serial::getParity () const +{ + return pimpl_->getParity (); +} + +void +Serial::setStopbits (stopbits_t stopbits) +{ + pimpl_->setStopbits (stopbits); +} + +stopbits_t +Serial::getStopbits () const +{ + return pimpl_->getStopbits (); +} + +void +Serial::setFlowcontrol (flowcontrol_t flowcontrol) +{ + pimpl_->setFlowcontrol (flowcontrol); +} + +flowcontrol_t +Serial::getFlowcontrol () const +{ + return pimpl_->getFlowcontrol (); +} + +void Serial::flush () +{ + ScopedReadLock rlock(this->pimpl_); + ScopedWriteLock wlock(this->pimpl_); + pimpl_->flush (); +} + +void Serial::flushInput () +{ + ScopedReadLock lock(this->pimpl_); + pimpl_->flushInput (); +} + +void Serial::flushOutput () +{ + ScopedWriteLock lock(this->pimpl_); + pimpl_->flushOutput (); +} + +void Serial::sendBreak (int duration) +{ + pimpl_->sendBreak (duration); +} + +void Serial::setBreak (bool level) +{ + pimpl_->setBreak (level); +} + +void Serial::setRTS (bool level) +{ + pimpl_->setRTS (level); +} + +void Serial::setDTR (bool level) +{ + pimpl_->setDTR (level); +} + +bool Serial::waitForChange() +{ + return pimpl_->waitForChange(); +} + +bool Serial::getCTS () +{ + return pimpl_->getCTS (); +} + +bool Serial::getDSR () +{ + return pimpl_->getDSR (); +} + +bool Serial::getRI () +{ + return pimpl_->getRI (); +} + +bool Serial::getCD () +{ + return pimpl_->getCD (); +} From 222cddc72152ec2e5c1037f8a0c64eac7f380877 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 24 Jul 2017 23:47:03 +0300 Subject: [PATCH 005/336] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BD=D1=82=D1=8B,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D1=8E=D1=82=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=80=D0=BE=D0=B1=D0=BE=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 67 ++++++++++++++++++++------------------ code/Arduino/Constants.h | 64 ++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 65 deletions(-) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 01c2e46..3ddf08b 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -1,41 +1,44 @@ #include "Constants.h" +/* Bluetooth */ +const uint8_t Constants::bluetooth_RX = 50; +const uint8_t Constants::bluetooth_TX = 51; +const uint32_t Constants::bluetooth_serial_speed = 9600; + +/* Wi-fi */ +const uint8_t Constants::wifi_RX = 30; +const uint8_t Constants::wifi_TX = 31; +const uint32_t Constants::wifi_serial_speed = 9600; + +/* Movement controller (L298N) */ +const uint8_t Constants::left_engine_enable = A8; +const uint8_t Constants::left_engine_straight_pin = 30; +const uint8_t Constants::left_engine_reverse_pin = 31; +const uint8_t Constants::right_engine_straight_pin = 32; +const uint8_t Constants::right_engine_reverse_pin = 33; +const uint8_t Constants::right_engine_enable = A9; + +/* Distanse controller */ +const uint8_t Constants::distance_sensor_read_pin = A0; +const uint8_t Constants::distance_sensor_a_pin = 4; +const uint8_t Constants::distance_sensor_b_pin = 5; +const uint8_t Constants::distance_sensor_c_pin = 6; + +/* Line controller */ +const uint8_t Constants::line_sensor_read_pin = A1; +const uint8_t Constants::line_sensor_a_pin = 15; +const uint8_t Constants::line_sensor_b_pin = 16; +const uint8_t Constants::line_sensor_c_pin = 17; + +const uint8_t Constants::servo_horizontal_pin = 34; +const uint8_t Constants::servo_vertical_pin = 35; + +const char Constants::commands_delimetr = ';'; + Constants::Constants() { - bluetooth_RX = 50; - bluetooth_TX = 51; - bluetooth_serial_speed = 9600; - - wifi_RX = 30; - wifi_TX = 31; - wifi_serial_speed = 9600; - - left_engine_enable = 7; - left_engine_straight_pin = 8; - left_engine_reverse_pin = 9; - right_engine_straight_pin = 10; - right_engine_reverse_pin = 11; - right_engine_enable = 12; - - /*distance_sensor_read_pin = A0;*/ - distance_sensor_a_pin = 4; - distance_sensor_b_pin = 5; - distance_sensor_c_pin = 6; - - //line_sensor_read_pin = A1; - line_sensor_a_pin = 15; - line_sensor_b_pin = 16; - line_sensor_c_pin = 17; - - servo_horizontal_pin = 34; - servo_vertical_pin = 35; - - commands_delimetr = ';'; } - Constants::~Constants() { } - - diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index 7bc6e8c..a1a5464 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -1,40 +1,38 @@ -#pragma once -#include +#pragma once +#include class Constants { public: - int bluetooth_RX; - int bluetooth_TX; - int bluetooth_serial_speed; - - int wifi_RX; - int wifi_TX; - int wifi_serial_speed; - - int left_engine_straight_pin; - int left_engine_reverse_pin; - int right_engine_straight_pin; - int right_engine_reverse_pin; - - int left_engine_enable; - int right_engine_enable; - - long distance_sensor_read_pin; - int distance_sensor_a_pin; - int distance_sensor_b_pin; - int distance_sensor_c_pin; - - - long line_sensor_read_pin; - int line_sensor_a_pin; - int line_sensor_b_pin; - int line_sensor_c_pin; - - int servo_horizontal_pin; - int servo_vertical_pin; - - char commands_delimetr; + static const uint8_t bluetooth_RX; + static const uint8_t bluetooth_TX; + static const uint32_t bluetooth_serial_speed; + + static const uint8_t wifi_RX; + static const uint8_t wifi_TX; + static const uint32_t wifi_serial_speed; + + static const uint8_t left_engine_enable; + static const uint8_t left_engine_straight_pin; + static const uint8_t left_engine_reverse_pin; + static const uint8_t right_engine_straight_pin; + static const uint8_t right_engine_reverse_pin; + static const uint8_t right_engine_enable; + + static const uint8_t distance_sensor_read_pin; + static const uint8_t distance_sensor_a_pin; + static const uint8_t distance_sensor_b_pin; + static const uint8_t distance_sensor_c_pin; + + static const uint8_t line_sensor_read_pin; + static const uint8_t line_sensor_a_pin; + static const uint8_t line_sensor_b_pin; + static const uint8_t line_sensor_c_pin; + + static const uint8_t servo_horizontal_pin; + static const uint8_t servo_vertical_pin; + + static const char commands_delimetr; Constants(); ~Constants(); From 3f9605f70c31d565affa7e386b550b14d813e015 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 25 Jul 2017 00:35:23 +0300 Subject: [PATCH 006/336] =?UTF-8?q?*=20gitignore=20=D0=B1=D1=8B=D0=BB=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20c++=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20*=20Arduino=20-=20=D0=BF=D0=BE=D1=84=D0=B8=D0=BA?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB?= =?UTF-8?q?=D1=8F=D1=86=D0=B8=D1=8F=20*=20cxx-api=20-=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=20=D0=BF=D1=83=D1=82=D1=8C=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=20*=20cxx-app=20-=20=D0=BD=D0=B0=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B8=D1=82=D0=B8?= =?UTF-8?q?=D0=B2=D0=BD=D1=8B=D0=B9=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=20(=D0=BF=D0=BE=D0=BA=D0=B0=20=D0=BD=D0=B5=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=BF=D0=B8=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 4 +- code/Arduino/Constants.h | 4 +- code/c++/cxx-api/.gitignore | 298 +++++++++++++++++++++++ code/c++/cxx-api/cxx-api.vcxproj | 4 + code/c++/cxx-app/.gitignore | 298 +++++++++++++++++++++++ code/c++/cxx-app/cxx-app.sln | 28 +++ code/c++/cxx-app/cxx-app.vcxproj | 163 +++++++++++++ code/c++/cxx-app/cxx-app.vcxproj.filters | 22 ++ code/c++/cxx-app/main.cpp | 21 ++ 9 files changed, 838 insertions(+), 4 deletions(-) create mode 100644 code/c++/cxx-api/.gitignore create mode 100644 code/c++/cxx-app/.gitignore create mode 100644 code/c++/cxx-app/cxx-app.sln create mode 100644 code/c++/cxx-app/cxx-app.vcxproj create mode 100644 code/c++/cxx-app/cxx-app.vcxproj.filters create mode 100644 code/c++/cxx-app/main.cpp diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 5949c9e..59c299c 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -32,11 +32,11 @@ const char Constants::commands_delimetr = ';'; const uint8_t Constants::min_speed = 0; const uint8_t Constants::max_speed = 255; -const uint8_t Constants::servo_delay = 20; +const uint16_t Constants::servo_delay = 20; const uint8_t Constants::countDistanceSensors = 5; const uint8_t Constants::countLineSensors = 5; -const uint8_t Constants::minimalLineBound = 270; +const uint16_t Constants::minimalLineBound = 270; Constants::Constants() { diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index 237ff00..5a9910e 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -41,8 +41,8 @@ class Constants static const uint8_t max_speed; static const uint16_t servo_delay; - static const uint16_t countDistanceSensors; - static const uint16_t countLineSensors; + static const uint8_t countDistanceSensors; + static const uint8_t countLineSensors; static const uint16_t minimalLineBound; Constants(); diff --git a/code/c++/cxx-api/.gitignore b/code/c++/cxx-api/.gitignore new file mode 100644 index 0000000..00a8775 --- /dev/null +++ b/code/c++/cxx-api/.gitignore @@ -0,0 +1,298 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# AJIOB_Exclude +Output \ No newline at end of file diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index cf3165c..03687b2 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -72,15 +72,19 @@ $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ diff --git a/code/c++/cxx-app/.gitignore b/code/c++/cxx-app/.gitignore new file mode 100644 index 0000000..00a8775 --- /dev/null +++ b/code/c++/cxx-app/.gitignore @@ -0,0 +1,298 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# AJIOB_Exclude +Output \ No newline at end of file diff --git a/code/c++/cxx-app/cxx-app.sln b/code/c++/cxx-app/cxx-app.sln new file mode 100644 index 0000000..652bc5b --- /dev/null +++ b/code/c++/cxx-app/cxx-app.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-app", "cxx-app.vcxproj", "{F92E7862-33C4-48B8-A055-3EE00352161F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x64.ActiveCfg = Debug|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x64.Build.0 = Debug|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x86.ActiveCfg = Debug|Win32 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x86.Build.0 = Debug|Win32 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x64.ActiveCfg = Release|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x64.Build.0 = Release|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x86.ActiveCfg = Release|Win32 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj new file mode 100644 index 0000000..914fa1a --- /dev/null +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {F92E7862-33C4-48B8-A055-3EE00352161F} + Win32Proj + cxxapp + 10.0.14393.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + + + true + $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + + + false + $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + + + false + $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/code/c++/cxx-app/cxx-app.vcxproj.filters b/code/c++/cxx-app/cxx-app.vcxproj.filters new file mode 100644 index 0000000..0d8d9e4 --- /dev/null +++ b/code/c++/cxx-app/cxx-app.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp new file mode 100644 index 0000000..e41271a --- /dev/null +++ b/code/c++/cxx-app/main.cpp @@ -0,0 +1,21 @@ +#include +#include + +#include "TrackPlatform_Manager.h" + +int main(int argc, char* argv[]) +{ + std::string rx, tx; + + std::cout << "rx" << std::endl; + std::cin >> rx; + std::cout << "tx" << std::endl; + std::cin >> tx; + + std::cout << "rx = " << rx << " tx = " << tx << std::endl; + + TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, 9600); + + return 0; +} + From bf513d5ab5d3735eed6a7c24b7804d24e00da576 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 25 Jul 2017 00:55:35 +0300 Subject: [PATCH 007/336] =?UTF-8?q?*=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8?= =?UTF-8?q?=D0=BB=D1=8F=D1=86=D0=B8=D1=8F=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5?= =?UTF-8?q?=D1=80=D0=B0.=20=D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D1=80=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=83=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=20(=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9)=20*=20=D0=92=20=D1=80=D0=B5=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=20=D1=81=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicConnector.cpp | 4 ++++ code/c++/cxx-api/TrackPlatform_BasicConnector.h | 2 +- code/c++/cxx-app/cxx-app.sln | 13 +++++++++++++ code/c++/cxx-app/cxx-app.vcxproj | 8 ++++---- code/c++/cxx-app/main.cpp | 10 +++++++++- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index f0f74bf..df6c986 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -4,3 +4,7 @@ TrackPlatform_BasicConnector::TrackPlatform_BasicConnector(const std::string& rx rxLocation(rx), txLocation(tx), baudRate(baudRate) { } + +TrackPlatform_BasicConnector::~TrackPlatform_BasicConnector() +{ +} diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index f5729c3..8a6dc5f 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -12,7 +12,7 @@ class TrackPlatform_BasicConnector public: TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); - virtual ~TrackPlatform_BasicConnector() = 0; + virtual ~TrackPlatform_BasicConnector(); virtual std::string read() = 0; virtual void write(const std::string& s) = 0; diff --git a/code/c++/cxx-app/cxx-app.sln b/code/c++/cxx-app/cxx-app.sln index 652bc5b..d3c2d65 100644 --- a/code/c++/cxx-app/cxx-app.sln +++ b/code/c++/cxx-app/cxx-app.sln @@ -4,6 +4,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 15.0.26430.13 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-app", "cxx-app.vcxproj", "{F92E7862-33C4-48B8-A055-3EE00352161F}" + ProjectSection(ProjectDependencies) = postProject + {32D3778A-E59E-4DBC-8D86-BD23B708CA12} = {32D3778A-E59E-4DBC-8D86-BD23B708CA12} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-api", "..\cxx-api\cxx-api.vcxproj", "{32D3778A-E59E-4DBC-8D86-BD23B708CA12}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +26,14 @@ Global {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x64.Build.0 = Release|x64 {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x86.ActiveCfg = Release|Win32 {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x86.Build.0 = Release|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x64.ActiveCfg = Debug|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x64.Build.0 = Debug|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x86.ActiveCfg = Debug|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x86.Build.0 = Debug|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.ActiveCfg = Release|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.Build.0 = Release|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.ActiveCfg = Release|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 914fa1a..a1f5544 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -74,23 +74,23 @@ true $(SolutionDir)..\cxx-api;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(OutDir);$(LibraryPath) true $(SolutionDir)..\cxx-api;$(IncludePath) - $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ false $(SolutionDir)..\cxx-api;$(IncludePath) - $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ false - $(SolutionDir)..\cxx-api\Output\$(Configuration)-$(Platform);$(LibraryPath) + $(OutDir);$(LibraryPath) $(SolutionDir)..\cxx-api;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index e41271a..1d76227 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -14,7 +14,15 @@ int main(int argc, char* argv[]) std::cout << "rx = " << rx << " tx = " << tx << std::endl; - TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, 9600); + try + { + TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, 9600U); + } + catch(...) + { + std::cout << "Exception was catched" << std::endl; + return 1; + } return 0; } From c89c1621499195a6956e46859d7024b944cbe6a9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 25 Jul 2017 11:39:34 +0300 Subject: [PATCH 008/336] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D1=81=D1=82=D0=B5?= =?UTF-8?q?=D0=B9=D1=88=D0=B8=D0=B9=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BD=D0=B0=20windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/.gitignore | 3 ++- code/c++/cxx-api/cxx-api.vcxproj | 4 ++++ code/c++/cxx-app/.gitignore | 3 ++- code/c++/cxx-app/cxx-app.vcxproj | 12 ++++++++++++ code/c++/cxx-app/main.cpp | 28 ++++++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-api/.gitignore b/code/c++/cxx-api/.gitignore index 00a8775..1d434d3 100644 --- a/code/c++/cxx-api/.gitignore +++ b/code/c++/cxx-api/.gitignore @@ -295,4 +295,5 @@ __pycache__/ *.xsd.cs # AJIOB_Exclude -Output \ No newline at end of file +Output +Build* diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 03687b2..84e8514 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -73,18 +73,22 @@ $(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ $(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ $(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ $(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ diff --git a/code/c++/cxx-app/.gitignore b/code/c++/cxx-app/.gitignore index 00a8775..1d434d3 100644 --- a/code/c++/cxx-app/.gitignore +++ b/code/c++/cxx-app/.gitignore @@ -295,4 +295,5 @@ __pycache__/ *.xsd.cs # AJIOB_Exclude -Output \ No newline at end of file +Output +Build* diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index a1f5544..34b7509 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -75,24 +75,28 @@ $(SolutionDir)..\cxx-api;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(OutDir);$(LibraryPath) + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ true $(SolutionDir)..\cxx-api;$(IncludePath) $(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ false $(SolutionDir)..\cxx-api;$(IncludePath) $(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ false $(OutDir);$(LibraryPath) $(SolutionDir)..\cxx-api;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ @@ -101,6 +105,8 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + Console @@ -114,6 +120,8 @@ Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + Console @@ -129,6 +137,8 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + Console @@ -146,6 +156,8 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + Console diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 1d76227..ca87b8d 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -1,6 +1,10 @@ #include #include +#if defined(_WIN32) +#include +#endif + #include "TrackPlatform_Manager.h" int main(int argc, char* argv[]) @@ -17,6 +21,30 @@ int main(int argc, char* argv[]) try { TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, 9600U); + while (true) + { + char c = _getch(); + if (c == '\b') //Backspace escape symbol + { + std::cout << "Back"; + break; + } + + switch (c) + { + case 'w': + trackPlatform.moveForward(); + break; + case 's': + trackPlatform.moveBackward(); + break; + case ' ': + trackPlatform.moveStopAll(); + break; + default: + break; + } + } } catch(...) { From 6b5fd1268703ccd9bbebc3956de642a9ac2ae578 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 25 Jul 2017 15:05:54 +0300 Subject: [PATCH 009/336] =?UTF-8?q?*=20BluetoothConnector=20->=20SerialCon?= =?UTF-8?q?nector=20*=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=20=D0=B4=D0=BB=D1=8F=20=D1=80=D1=83=D1=87?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20(SerialConnector)=20*=20?= =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=82?= =?UTF-8?q?=D0=B0=D0=B9=D0=BC=D0=B5=D1=80=20=D0=B4=D0=BB=D1=8F=20"=D1=81?= =?UTF-8?q?=D0=B1=D0=BE=D1=80=D0=B0"=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=D0=B0=20=D0=B8=D0=B7=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=BF=D0=BE=D1=80=D1=82=D0=B0=20*=20=D0=94=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7?= =?UTF-8?q?=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=20=D0=BC?= =?UTF-8?q?=D0=B3=D0=BD=D0=BE=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2?= =?UTF-8?q?=D1=81=D0=B5=D0=B3=D0=BE,=20=D1=87=D1=82=D0=BE=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D1=87=D0=B8=D1=82=D0=B0=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D0=B0=20(=D0=BD=D0=B0=20=D1=83=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BD=D0=B5=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5?= =?UTF-8?q?=D0=B9=D1=81=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/BluetoothConnector.cpp | 30 ------------- code/c++/cxx-api/SerialConnector.cpp | 36 ++++++++++++++++ ...BluetoothConnector.h => SerialConnector.h} | 8 ++-- .../cxx-api/TrackPlatform_BasicConnector.h | 1 + code/c++/cxx-api/TrackPlatform_Manager.cpp | 4 +- code/c++/cxx-api/cxx-api.vcxproj | 4 +- code/c++/cxx-api/cxx-api.vcxproj.filters | 4 +- code/c++/cxx-app/cxx-app.vcxproj | 8 ++-- code/c++/cxx-app/main.cpp | 42 ++++++++----------- 9 files changed, 70 insertions(+), 67 deletions(-) delete mode 100644 code/c++/cxx-api/BluetoothConnector.cpp create mode 100644 code/c++/cxx-api/SerialConnector.cpp rename code/c++/cxx-api/{BluetoothConnector.h => SerialConnector.h} (60%) diff --git a/code/c++/cxx-api/BluetoothConnector.cpp b/code/c++/cxx-api/BluetoothConnector.cpp deleted file mode 100644 index fd3105e..0000000 --- a/code/c++/cxx-api/BluetoothConnector.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "BluetoothConnector.h" - -BluetoothConnector::BluetoothConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) - : TrackPlatform_BasicConnector(rx, tx, baudRate), readPort(new serial::Serial(rx, baudRate)), writePort((rx == tx) ? readPort : new serial::Serial(tx, baudRate)) -{ -} - -BluetoothConnector::~BluetoothConnector() -{ - if (readPort != writePort) - { - delete writePort; - } - delete readPort; -} - -std::string BluetoothConnector::read() -{ - return readPort->read(messageMaxSize); -} - -void BluetoothConnector::write(const std::string& s) -{ - writePort->write(s); -} - -bool BluetoothConnector::isConnected() -{ - return (readPort->isOpen() && writePort->isOpen()); -} diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp new file mode 100644 index 0000000..8e0476b --- /dev/null +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -0,0 +1,36 @@ +#include "SerialConnector.h" + +SerialConnector::SerialConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : + TrackPlatform_BasicConnector(rx, tx, baudRate), readPort(new serial::Serial(rx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))), + writePort((rx == tx) ? readPort : new serial::Serial(tx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))) +{ +} + +SerialConnector::~SerialConnector() +{ + if (readPort != writePort) + { + delete writePort; + } + delete readPort; +} + +std::string SerialConnector::read() +{ + return readPort->read(messageMaxSize); +} + +std::string SerialConnector::readAllAvailable() +{ + return (readPort->available() ? readPort->read(readPort->available()) : ""); +} + +void SerialConnector::write(const std::string& s) +{ + writePort->write(s); +} + +bool SerialConnector::isConnected() +{ + return (readPort->isOpen() && writePort->isOpen()); +} diff --git a/code/c++/cxx-api/BluetoothConnector.h b/code/c++/cxx-api/SerialConnector.h similarity index 60% rename from code/c++/cxx-api/BluetoothConnector.h rename to code/c++/cxx-api/SerialConnector.h index 3b67d02..6b448bd 100644 --- a/code/c++/cxx-api/BluetoothConnector.h +++ b/code/c++/cxx-api/SerialConnector.h @@ -4,17 +4,19 @@ #include "TrackPlatform_BasicConnector.h" #include "serial/serial.h" -class BluetoothConnector : public TrackPlatform_BasicConnector +class SerialConnector : public TrackPlatform_BasicConnector { static const size_t messageMaxSize = 65535; + static const size_t timeoutInMs = 500; serial::Serial* readPort; serial::Serial* writePort; public: - BluetoothConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); - ~BluetoothConnector() override; + SerialConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); + ~SerialConnector() override; std::string read() override; + std::string readAllAvailable() override; void write(const std::string& s) override; bool isConnected() override; }; diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index 8a6dc5f..c196387 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -15,6 +15,7 @@ class TrackPlatform_BasicConnector virtual ~TrackPlatform_BasicConnector(); virtual std::string read() = 0; + virtual std::string readAllAvailable() = 0; virtual void write(const std::string& s) = 0; virtual bool isConnected() = 0; }; diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index cf942b6..595ea83 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -1,5 +1,5 @@ #include "TrackPlatform_Manager.h" -#include "BluetoothConnector.h" +#include "SerialConnector.h" TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate) { @@ -9,7 +9,7 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne switch (mode) { case bluetooth: - res = new BluetoothConnector(rx, tx, baudRate); + res = new SerialConnector(rx, tx, baudRate); break; default: res = nullptr; diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 84e8514..4b18457 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -147,7 +147,7 @@ - + @@ -158,7 +158,7 @@ - + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index bb6dabe..19e9a30 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -48,7 +48,7 @@ Header Files - + Header Files @@ -71,7 +71,7 @@ Source Files - + Source Files diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 34b7509..7bc717f 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -72,21 +72,21 @@ true - $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(OutDir);$(LibraryPath) $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ true - $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ false - $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ @@ -94,7 +94,7 @@ false $(OutDir);$(LibraryPath) - $(SolutionDir)..\cxx-api;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index ca87b8d..a35c9d3 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -5,45 +5,39 @@ #include #endif -#include "TrackPlatform_Manager.h" +//#include "TrackPlatform_Manager.h" +#include "SerialConnector.h" int main(int argc, char* argv[]) { - std::string rx, tx; + std::string rx = "COM6", tx = "COM6"; + uint32_t baudrate = 9600U; - std::cout << "rx" << std::endl; + /*std::cout << "rx" << std::endl; std::cin >> rx; std::cout << "tx" << std::endl; std::cin >> tx; - - std::cout << "rx = " << rx << " tx = " << tx << std::endl; + std::cout << "baudrate" << std::endl; + std::cin >> baudrate; +*/ + std::cout << "rx = " << rx << " tx = " << tx << " baudrate = " << baudrate << std::endl; try { - TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, 9600U); + SerialConnector connector(rx, tx, baudrate); + //TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, baudrate); while (true) { - char c = _getch(); - if (c == '\b') //Backspace escape symbol - { - std::cout << "Back"; - break; - } - - switch (c) + std::string s; + std::cout << "Request: "; + std::cin >> s; + while (std::cin.get() != '\n'){ } + if (s == "quit") { - case 'w': - trackPlatform.moveForward(); - break; - case 's': - trackPlatform.moveBackward(); - break; - case ' ': - trackPlatform.moveStopAll(); - break; - default: break; } + connector.write(s); + std::cout << "Answer: " << connector.read() << std::endl; } } catch(...) From e12e05dc3b868daa330a26364ff4c4d05a3c0c67 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 25 Jul 2017 20:48:13 +0300 Subject: [PATCH 010/336] Not checked on device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Добавлена поддержка UART для посылки команд (14 и 15 порт) * В README добавлена информация о поддержке printf --- README.md | 2 ++ code/Arduino/ConnectingDevice.h | 2 +- code/Arduino/Constants.cpp | 5 +++++ code/Arduino/Constants.h | 4 ++++ code/Arduino/ServoController.cpp | 2 +- code/Arduino/ServoController.h | 3 ++- code/Arduino/UART.cpp | 9 +++++++++ code/Arduino/UART.h | 9 +++++++++ code/Arduino/trackPlatform.ino | 15 +++++++-------- 9 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 code/Arduino/UART.cpp create mode 100644 code/Arduino/UART.h diff --git a/README.md b/README.md index 9d4f767..759ebf7 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ - Драйвер двигателя (L298N) - Поворотная платформа +Для отладки требуется небольная модификация исходников Arduino IDE в соответствии с [этой](https://playground.arduino.cc/Main/Printf) статьей. + Датчики расстояния объедены в модуль, который несложно снимается, что позволяет заменить датчики. В модуле 5 датчиков расстояния, расположенных под различными углами для улучшения ориентирования на местности. Так же углы поворота датчиков можно настраивать в небольшом диапазоне. Расположены спереди платформы. ![](https://pp.userapi.com/c626121/v626121114/60cc7/xe6EOab8Ysw.jpg) diff --git a/code/Arduino/ConnectingDevice.h b/code/Arduino/ConnectingDevice.h index 888b998..b64363b 100644 --- a/code/Arduino/ConnectingDevice.h +++ b/code/Arduino/ConnectingDevice.h @@ -7,7 +7,7 @@ class ConnectingDevice SoftwareSerial *device; public: - ConnectingDevice(int, int, int); + ConnectingDevice(int rx, int tx, int speed); bool isActive(); String read(); void send(String data); diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 3ddf08b..5d84e31 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -10,6 +10,11 @@ const uint8_t Constants::wifi_RX = 30; const uint8_t Constants::wifi_TX = 31; const uint32_t Constants::wifi_serial_speed = 9600; +/* Wi-fi */ +const uint8_t Constants::uart_RX = 14; +const uint8_t Constants::uart_TX = 15; +const uint32_t Constants::uart_serial_speed = 9600; + /* Movement controller (L298N) */ const uint8_t Constants::left_engine_enable = A8; const uint8_t Constants::left_engine_straight_pin = 30; diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index a1a5464..30669e8 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -12,6 +12,10 @@ class Constants static const uint8_t wifi_TX; static const uint32_t wifi_serial_speed; + static const uint8_t uart_RX; + static const uint8_t uart_TX; + static const uint32_t uart_serial_speed; + static const uint8_t left_engine_enable; static const uint8_t left_engine_straight_pin; static const uint8_t left_engine_reverse_pin; diff --git a/code/Arduino/ServoController.cpp b/code/Arduino/ServoController.cpp index 3f5ab65..dceb034 100644 --- a/code/Arduino/ServoController.cpp +++ b/code/Arduino/ServoController.cpp @@ -4,7 +4,7 @@ ServoController::ServoController() { - + init(); } void ServoController::init() { diff --git a/code/Arduino/ServoController.h b/code/Arduino/ServoController.h index 6a3dbcf..ef02d97 100644 --- a/code/Arduino/ServoController.h +++ b/code/Arduino/ServoController.h @@ -10,10 +10,11 @@ class ServoController : public MainController Servo horizontalServo; Servo verticalServo; + void init(); + public: Constants constants; ServoController(); - void init(); void exec(ConnectingDevice*, String); void setHorizontalAngle(int angle); void setVerticalAngle(int angle); diff --git a/code/Arduino/UART.cpp b/code/Arduino/UART.cpp new file mode 100644 index 0000000..efc2d9b --- /dev/null +++ b/code/Arduino/UART.cpp @@ -0,0 +1,9 @@ +#include "UART.h" + +UART::UART(int rx, int tx, int baudrate): ConnectingDevice(rx, tx, baudrate) +{ +} + +UART::~UART() +{ +} diff --git a/code/Arduino/UART.h b/code/Arduino/UART.h new file mode 100644 index 0000000..c823e68 --- /dev/null +++ b/code/Arduino/UART.h @@ -0,0 +1,9 @@ +#pragma once +#include "ConnectingDevice.h" + +class UART : public ConnectingDevice +{ +public: + UART(int rx, int tx, int baudrate); + ~UART(); +}; diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 30bea26..9dba940 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -1,3 +1,4 @@ +#include "UART.h" #include "Constants.h" #include "ConnectingDevice.h" #include "Bluetooth.h" @@ -9,16 +10,14 @@ Constants constants; Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bluetooth_serial_speed); WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); +UART uart(constants.uart_RX, constants.uart_TX, constants.uart_serial_speed); ConnectingDevice *device; CommandsController controller; -ServoController servoController; bool connected = false; void setup() { - servoController.init(); - while (!connected) { if (bluetooth.isActive()) { connected = true; @@ -28,6 +27,10 @@ void setup() connected = true; device = &wifi; } + else if (uart.isActive()) { + connected = true; + device = &uart; + } } } @@ -35,9 +38,5 @@ void loop() { delay(100); //for sending commands from mobile String command = device->read(); - if (command[0] == servoControllerID) { - servoController.exec(device, command); - } else { - controller.handle(device, command); - } + controller.handle(device, command); } From a6cf607f91b8959288d7988ea82f1a0e46a090d5 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 25 Jul 2017 23:50:26 +0300 Subject: [PATCH 011/336] Arduino MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Все отсортировано по папкам --- code/Arduino/CommandsController.cpp | 3 +- code/Arduino/CommandsController.h | 11 +++--- code/Arduino/{ => connectors}/Bluetooth.cpp | 0 code/Arduino/{ => connectors}/Bluetooth.h | 0 .../{ => connectors}/ConnectingDevice.cpp | 0 .../{ => connectors}/ConnectingDevice.h | 3 +- code/Arduino/{ => connectors}/UART.cpp | 0 code/Arduino/{ => connectors}/UART.h | 0 code/Arduino/{ => connectors}/WiFi.cpp | 0 code/Arduino/{ => connectors}/WiFi.h | 0 .../{ => peripheral}/MainController.cpp | 0 .../Arduino/{ => peripheral}/MainController.h | 7 ++-- .../{ => peripheral}/MovementController.cpp | 3 +- .../{ => peripheral}/MovementController.h | 5 +-- .../{ => peripheral}/SensorsController.cpp | 2 +- .../{ => peripheral}/SensorsController.h | 10 ++---- .../{ => peripheral}/ServoController.cpp | 4 +-- .../{ => peripheral}/ServoController.h | 4 --- code/Arduino/trackPlatform.ino | 14 ++------ code/Arduino/trackPlatform.vcxproj | 28 +++++++-------- code/Arduino/trackPlatform.vcxproj.filters | 36 +++++++++---------- 21 files changed, 52 insertions(+), 78 deletions(-) rename code/Arduino/{ => connectors}/Bluetooth.cpp (100%) rename code/Arduino/{ => connectors}/Bluetooth.h (100%) rename code/Arduino/{ => connectors}/ConnectingDevice.cpp (100%) rename code/Arduino/{ => connectors}/ConnectingDevice.h (91%) rename code/Arduino/{ => connectors}/UART.cpp (100%) rename code/Arduino/{ => connectors}/UART.h (100%) rename code/Arduino/{ => connectors}/WiFi.cpp (100%) rename code/Arduino/{ => connectors}/WiFi.h (100%) rename code/Arduino/{ => peripheral}/MainController.cpp (100%) rename code/Arduino/{ => peripheral}/MainController.h (68%) rename code/Arduino/{ => peripheral}/MovementController.cpp (99%) rename code/Arduino/{ => peripheral}/MovementController.h (93%) rename code/Arduino/{ => peripheral}/SensorsController.cpp (99%) rename code/Arduino/{ => peripheral}/SensorsController.h (79%) rename code/Arduino/{ => peripheral}/ServoController.cpp (95%) rename code/Arduino/{ => peripheral}/ServoController.h (86%) diff --git a/code/Arduino/CommandsController.cpp b/code/Arduino/CommandsController.cpp index 9c6e0f0..fc27c0d 100644 --- a/code/Arduino/CommandsController.cpp +++ b/code/Arduino/CommandsController.cpp @@ -1,7 +1,6 @@ +#include "CommandsEnum.h" #include "CommandsController.h" - - CommandsController::CommandsController() { } diff --git a/code/Arduino/CommandsController.h b/code/Arduino/CommandsController.h index 9507744..d21ea74 100644 --- a/code/Arduino/CommandsController.h +++ b/code/Arduino/CommandsController.h @@ -1,14 +1,13 @@ #pragma once -#include "ConnectingDevice.h" -#include "MovementController.h" -#include "SensorsController.h" -#include "ServoController.h" -#include "CommandsEnum.h" +#include +#include "peripheral/MovementController.h" +#include "peripheral/SensorsController.h" +#include "peripheral/ServoController.h" +#include "connectors/ConnectingDevice.h" class CommandsController { -private: MovementController moveController; SensorsController sensorsController; ServoController servoController; diff --git a/code/Arduino/Bluetooth.cpp b/code/Arduino/connectors/Bluetooth.cpp similarity index 100% rename from code/Arduino/Bluetooth.cpp rename to code/Arduino/connectors/Bluetooth.cpp diff --git a/code/Arduino/Bluetooth.h b/code/Arduino/connectors/Bluetooth.h similarity index 100% rename from code/Arduino/Bluetooth.h rename to code/Arduino/connectors/Bluetooth.h diff --git a/code/Arduino/ConnectingDevice.cpp b/code/Arduino/connectors/ConnectingDevice.cpp similarity index 100% rename from code/Arduino/ConnectingDevice.cpp rename to code/Arduino/connectors/ConnectingDevice.cpp diff --git a/code/Arduino/ConnectingDevice.h b/code/Arduino/connectors/ConnectingDevice.h similarity index 91% rename from code/Arduino/ConnectingDevice.h rename to code/Arduino/connectors/ConnectingDevice.h index b64363b..c1a643b 100644 --- a/code/Arduino/ConnectingDevice.h +++ b/code/Arduino/connectors/ConnectingDevice.h @@ -1,6 +1,7 @@ #pragma once #include -#include "Arduino.h" +#include + class ConnectingDevice { protected: diff --git a/code/Arduino/UART.cpp b/code/Arduino/connectors/UART.cpp similarity index 100% rename from code/Arduino/UART.cpp rename to code/Arduino/connectors/UART.cpp diff --git a/code/Arduino/UART.h b/code/Arduino/connectors/UART.h similarity index 100% rename from code/Arduino/UART.h rename to code/Arduino/connectors/UART.h diff --git a/code/Arduino/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp similarity index 100% rename from code/Arduino/WiFi.cpp rename to code/Arduino/connectors/WiFi.cpp diff --git a/code/Arduino/WiFi.h b/code/Arduino/connectors/WiFi.h similarity index 100% rename from code/Arduino/WiFi.h rename to code/Arduino/connectors/WiFi.h diff --git a/code/Arduino/MainController.cpp b/code/Arduino/peripheral/MainController.cpp similarity index 100% rename from code/Arduino/MainController.cpp rename to code/Arduino/peripheral/MainController.cpp diff --git a/code/Arduino/MainController.h b/code/Arduino/peripheral/MainController.h similarity index 68% rename from code/Arduino/MainController.h rename to code/Arduino/peripheral/MainController.h index a748f63..4e7a683 100644 --- a/code/Arduino/MainController.h +++ b/code/Arduino/peripheral/MainController.h @@ -1,9 +1,6 @@ #pragma once -#include "Arduino.h" -#include "Constants.h" -#include "CommandsEnum.h" -#include "HardwareSerial.h" -#include "ConnectingDevice.h" +#include +#include "..\Constants.h" class MainController { diff --git a/code/Arduino/MovementController.cpp b/code/Arduino/peripheral/MovementController.cpp similarity index 99% rename from code/Arduino/MovementController.cpp rename to code/Arduino/peripheral/MovementController.cpp index f6ba968..1eda164 100644 --- a/code/Arduino/MovementController.cpp +++ b/code/Arduino/peripheral/MovementController.cpp @@ -1,7 +1,6 @@ +#include "../CommandsEnum.h" #include "MovementController.h" - - MovementController::MovementController() { MIN_SPEED = constants.min_speed; diff --git a/code/Arduino/MovementController.h b/code/Arduino/peripheral/MovementController.h similarity index 93% rename from code/Arduino/MovementController.h rename to code/Arduino/peripheral/MovementController.h index abaf91f..d6768b9 100644 --- a/code/Arduino/MovementController.h +++ b/code/Arduino/peripheral/MovementController.h @@ -1,12 +1,10 @@ #pragma once +#include "../connectors/ConnectingDevice.h" #include "MainController.h" - - class MovementController : public MainController { -private: Constants constants; int MIN_SPEED; int MAX_SPEED; @@ -28,4 +26,3 @@ class MovementController : public MainController void stop_moving(); ~MovementController(); }; - diff --git a/code/Arduino/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp similarity index 99% rename from code/Arduino/SensorsController.cpp rename to code/Arduino/peripheral/SensorsController.cpp index ceb400a..62a4c8a 100644 --- a/code/Arduino/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -1,6 +1,6 @@ +#include "../CommandsEnum.h" #include "SensorsController.h" - SensorsController::SensorsController() { countDistanceSensors = constants.countDistanceSensors; diff --git a/code/Arduino/SensorsController.h b/code/Arduino/peripheral/SensorsController.h similarity index 79% rename from code/Arduino/SensorsController.h rename to code/Arduino/peripheral/SensorsController.h index a59c69a..fff8ec7 100644 --- a/code/Arduino/SensorsController.h +++ b/code/Arduino/peripheral/SensorsController.h @@ -1,22 +1,16 @@ #pragma once -#include "ConnectingDevice.h" -#include "Constants.h" -#include "Arduino.h" +#include +#include "../connectors/ConnectingDevice.h" #include "MainController.h" -#include "CommandsEnum.h" - - class SensorsController: public MainController { -private: int countDistanceSensors; int countLineSensors; int minimalLineBound; public: - Constants constants; SensorsController(); void exec(ConnectingDevice*, String); diff --git a/code/Arduino/ServoController.cpp b/code/Arduino/peripheral/ServoController.cpp similarity index 95% rename from code/Arduino/ServoController.cpp rename to code/Arduino/peripheral/ServoController.cpp index 3259d23..7d69624 100644 --- a/code/Arduino/ServoController.cpp +++ b/code/Arduino/peripheral/ServoController.cpp @@ -1,7 +1,7 @@ +#include "../CommandsEnum.h" +#include "../connectors/ConnectingDevice.h" #include "ServoController.h" - - ServoController::ServoController() { init(); diff --git a/code/Arduino/ServoController.h b/code/Arduino/peripheral/ServoController.h similarity index 86% rename from code/Arduino/ServoController.h rename to code/Arduino/peripheral/ServoController.h index ef02d97..5834ee7 100644 --- a/code/Arduino/ServoController.h +++ b/code/Arduino/peripheral/ServoController.h @@ -1,19 +1,15 @@ #pragma once #include -#include "Constants.h" -#include "ConnectingDevice.h" #include "MainController.h" class ServoController : public MainController { -private: Servo horizontalServo; Servo verticalServo; void init(); public: - Constants constants; ServoController(); void exec(ConnectingDevice*, String); void setHorizontalAngle(int angle); diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 9dba940..0df6613 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -1,16 +1,12 @@ -#include "UART.h" #include "Constants.h" -#include "ConnectingDevice.h" -#include "Bluetooth.h" -#include "WiFi.h" -#include "SoftwareSerial.h" +#include "connectors/WiFi.h" +#include "connectors/ConnectingDevice.h" +#include "connectors/Bluetooth.h" #include "CommandsController.h" -#include "ServoController.h" Constants constants; Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bluetooth_serial_speed); WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); -UART uart(constants.uart_RX, constants.uart_TX, constants.uart_serial_speed); ConnectingDevice *device; CommandsController controller; @@ -27,10 +23,6 @@ void setup() connected = true; device = &wifi; } - else if (uart.isActive()) { - connected = true; - device = &uart; - } } } diff --git a/code/Arduino/trackPlatform.vcxproj b/code/Arduino/trackPlatform.vcxproj index b2db8b8..2dbc857 100644 --- a/code/Arduino/trackPlatform.vcxproj +++ b/code/Arduino/trackPlatform.vcxproj @@ -85,30 +85,30 @@ - + - + - - + + - - - + + + - + - + - - - - - + + + + + diff --git a/code/Arduino/trackPlatform.vcxproj.filters b/code/Arduino/trackPlatform.vcxproj.filters index f8efdf5..a574af7 100644 --- a/code/Arduino/trackPlatform.vcxproj.filters +++ b/code/Arduino/trackPlatform.vcxproj.filters @@ -27,34 +27,34 @@ Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files @@ -62,28 +62,28 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files From b1d4b608918ec6145fecf90343725f789f072096 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 26 Jul 2017 00:25:35 +0300 Subject: [PATCH 012/336] =?UTF-8?q?*=20=D0=A3=D0=B1=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B4=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20UART=20*=20=D0=A1=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=20=D0=BC=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B4=D0=B2=D0=B8=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=80=D0=BE=D0=B1=D0=BE=D1=82=D0=B0=20=D0=BF=D0=BE=20Blueto?= =?UTF-8?q?oth=20(=D0=B8=D0=BB=D0=B8=20=D0=B4=D1=80=D1=83=D0=B3=D0=BE?= =?UTF-8?q?=D0=BC=D1=83=20=D1=83=D1=81=D1=82=D1=80=D0=BE=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D1=83,=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D1=83=D1=8E=D1=89=D0=B5=D0=BC=D1=83=20Serial=20potrs)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 5 ---- code/Arduino/Constants.h | 4 --- code/Arduino/connectors/UART.cpp | 9 ------ code/Arduino/connectors/UART.h | 9 ------ code/c++/cxx-app/main.cpp | 48 +++++++++++++++++++++++--------- 5 files changed, 35 insertions(+), 40 deletions(-) delete mode 100644 code/Arduino/connectors/UART.cpp delete mode 100644 code/Arduino/connectors/UART.h diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 2b71a90..469c23d 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -10,11 +10,6 @@ const uint8_t Constants::wifi_RX = 30; const uint8_t Constants::wifi_TX = 31; const uint32_t Constants::wifi_serial_speed = 9600; -/* Wi-fi */ -const uint8_t Constants::uart_RX = 14; -const uint8_t Constants::uart_TX = 15; -const uint32_t Constants::uart_serial_speed = 9600; - /* Movement controller (L298N) */ const uint8_t Constants::left_engine_enable = A8; const uint8_t Constants::left_engine_straight_pin = 30; diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index aae69d7..ec11485 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -12,10 +12,6 @@ class Constants static const uint8_t wifi_TX; static const uint32_t wifi_serial_speed; - static const uint8_t uart_RX; - static const uint8_t uart_TX; - static const uint32_t uart_serial_speed; - static const uint8_t left_engine_enable; static const uint8_t left_engine_straight_pin; static const uint8_t left_engine_reverse_pin; diff --git a/code/Arduino/connectors/UART.cpp b/code/Arduino/connectors/UART.cpp deleted file mode 100644 index efc2d9b..0000000 --- a/code/Arduino/connectors/UART.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "UART.h" - -UART::UART(int rx, int tx, int baudrate): ConnectingDevice(rx, tx, baudrate) -{ -} - -UART::~UART() -{ -} diff --git a/code/Arduino/connectors/UART.h b/code/Arduino/connectors/UART.h deleted file mode 100644 index c823e68..0000000 --- a/code/Arduino/connectors/UART.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "ConnectingDevice.h" - -class UART : public ConnectingDevice -{ -public: - UART(int rx, int tx, int baudrate); - ~UART(); -}; diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index a35c9d3..07f3486 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -5,12 +5,11 @@ #include #endif -//#include "TrackPlatform_Manager.h" -#include "SerialConnector.h" +#include "TrackPlatform_Manager.h" int main(int argc, char* argv[]) { - std::string rx = "COM6", tx = "COM6"; + std::string rx = "COM10", tx = "COM10"; uint32_t baudrate = 9600U; /*std::cout << "rx" << std::endl; @@ -24,20 +23,43 @@ int main(int argc, char* argv[]) try { - SerialConnector connector(rx, tx, baudrate); - //TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, baudrate); - while (true) + TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, baudrate); + bool isExit = false; + while (!isExit) { - std::string s; - std::cout << "Request: "; - std::cin >> s; - while (std::cin.get() != '\n'){ } - if (s == "quit") + auto c = _getche(); + + switch (c) { + case '0': + std::cout << "0: help"; + std::cout << "q: quit"; + std::cout << "w: move forward"; + std::cout << "s: move back"; + std::cout << "a: turn left (anticlockwise)"; + std::cout << "d: turn right (clockwise)"; + std::cout << " : stop"; + break; + case 'q': + isExit = true; + break; + case 'w': + trackPlatform.moveForward(); + break; + case 'a': + trackPlatform.moveBackward(); + break; + case 's': + trackPlatform.rotateAntiClockwise(); + break; + case 'd': + trackPlatform.rotateClockwise(); + break; + case ' ': + trackPlatform.moveStopAll(); break; + default: break; } - connector.write(s); - std::cout << "Answer: " << connector.read() << std::endl; } } catch(...) From 4d0861e40d8b54c774244517d1a78285df88bf5f Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 26 Jul 2017 10:32:09 +0300 Subject: [PATCH 013/336] =?UTF-8?q?*=20Arduino=20=D0=BF=D1=80=D0=BE=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=20=D1=80=D0=B0=D0=B7=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BC=20(=D0=BF=D0=B0=D0=BF=D0=BA=D0=B0=D0=BC)=20=D0=B2=20Visu?= =?UTF-8?q?al=20Studio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/trackPlatform.vcxproj.filters | 64 ++++++++++++++-------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/code/Arduino/trackPlatform.vcxproj.filters b/code/Arduino/trackPlatform.vcxproj.filters index a574af7..8fd3b0f 100644 --- a/code/Arduino/trackPlatform.vcxproj.filters +++ b/code/Arduino/trackPlatform.vcxproj.filters @@ -13,6 +13,24 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {d18e222c-a964-4c1b-af76-c7e6c7c79696} + + + {59c1c582-bece-4678-8894-1f186df97c5b} + + + {4d8737a4-6736-4d31-803f-f0f98e318ba5} + + + {8e5e8e86-61de-4400-bc87-9882d23f80b0} + + + {5a05d265-b32e-4399-9fbd-931b3b0be584} + + + {0331c73c-5716-43bd-a435-2ed6e0b5999b} + @@ -36,26 +54,26 @@ Header Files + + connectors\header + - Header Files + connectors\header - Header Files - - - Header Files - - - Header Files + connectors\header - Header Files + peripheral\header - Header Files + peripheral\header - - Header Files + + peripheral\header + + + peripheral\header @@ -66,25 +84,25 @@ Source Files - Source Files + connectors\source - Source Files + connectors\source + + + connectors\source + + + peripheral\source - Source Files + peripheral\source - Source Files + peripheral\source - Source Files - - - Source Files - - - Source Files + peripheral\source From 80c33259757aa7ef9d1d844ca6df00361c09a6a4 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 26 Jul 2017 15:19:09 +0300 Subject: [PATCH 014/336] =?UTF-8?q?*=20Arduino=20-=20=D0=9F=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=BA=D0=B0=20=D0=BF=D0=B0=D0=BC=D1=8F=D1=82=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=B8=D0=BA=D1=80=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=BB=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/peripheral/MovementController.cpp | 8 ++++++-- code/Arduino/peripheral/SensorsController.cpp | 10 ++++++++-- code/Arduino/peripheral/ServoController.cpp | 9 +++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/code/Arduino/peripheral/MovementController.cpp b/code/Arduino/peripheral/MovementController.cpp index 1eda164..1328216 100644 --- a/code/Arduino/peripheral/MovementController.cpp +++ b/code/Arduino/peripheral/MovementController.cpp @@ -17,6 +17,7 @@ MovementController::MovementController() } void MovementController::exec(ConnectingDevice *device, String command) { + int* arr = nullptr; switch (command[1]) { case forward: @@ -44,12 +45,15 @@ void MovementController::exec(ConnectingDevice *device, String command) { move_back(parse_command(command, 2, command.length())); break; case track_set_speed: - choose_track_set_speed(parse_command(command, 2, constants.commands_delimetr, 2)); + choose_track_set_speed(arr = parse_command(command, 2, constants.commands_delimetr, 2)); break; default: break; } - + if (arr) + { + delete[] arr; + } } diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index 62a4c8a..c1b73df 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -22,23 +22,28 @@ SensorsController::SensorsController() void SensorsController::exec(ConnectingDevice *device, String command) { + int *arr = nullptr; switch (command[1]) { case distance_sensor: device->send(String(getDistance(parse_command(command, 2, command.length())))); break; case distance_sensor_all: - device->send(intArrayToString(getDistanceAll(), countDistanceSensors)); + device->send(intArrayToString(arr = getDistanceAll(), countDistanceSensors)); break; case line_sensor: device->send(String(getLine(parse_command(command, 2, command.length())))); break; case line_sensor_all: - device->send(intArrayToString(getLineAll(), countLineSensors)); + device->send(intArrayToString(arr = getLineAll(), countLineSensors)); break; default: break; } + if (arr) + { + delete[] arr; + } } void SensorsController::chooseLineSensor(int number) { @@ -144,6 +149,7 @@ int SensorsController::getAverageDistance(int number, int n) { for (int i = 0; i < n; i++) { averageDistance += arr[i]; } + delete[] arr; return averageDistance / n; } diff --git a/code/Arduino/peripheral/ServoController.cpp b/code/Arduino/peripheral/ServoController.cpp index 7d69624..7639f50 100644 --- a/code/Arduino/peripheral/ServoController.cpp +++ b/code/Arduino/peripheral/ServoController.cpp @@ -15,6 +15,7 @@ void ServoController::init() { } void ServoController::exec(ConnectingDevice* device, String command) { + int* arr = nullptr; switch (command[1]) { case set_horizontal_angle: @@ -24,14 +25,18 @@ void ServoController::exec(ConnectingDevice* device, String command) { setVerticalAngle(parse_command(command, 2, command.length())); break; case set_horiz_vertical_angles: - setHorizontalAndVerticalAngle(parse_command(command, 2, constants.commands_delimetr, 2)); + setHorizontalAndVerticalAngle(arr = parse_command(command, 2, constants.commands_delimetr, 2)); break; case get_coodrinates: - device->send(intArrayToString(getCoordinates(), 2)); + device->send(intArrayToString(arr = getCoordinates(), 2)); break; default: break; } + if (arr) + { + delete[] arr; + } } void ServoController::setHorizontalAngle(int angle) { From a20f925fa4ab665bb1085a449f818ffae132a665 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 28 Jul 2017 00:42:56 +0300 Subject: [PATCH 015/336] Arduino code changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * добавлена поддержка USB (через USB type B на плате (Serial)) * Поправлен класс ConnectingDevice на более обобщенный * Добавлен UART для отладки (пины 52-53) - cxx-api: * Добавлена обработка ошибок в случае некорректного ответа от контроллера - cxx-app: * Добавлены функции получения данных с датчиков линий --- code/Arduino/Constants.cpp | 5 +++ code/Arduino/Constants.h | 4 +++ code/Arduino/connectors/ConnectingDevice.cpp | 12 ++++--- code/Arduino/connectors/ConnectingDevice.h | 5 +-- code/Arduino/connectors/DebugSerial.cpp | 21 +++++++++++ code/Arduino/connectors/DebugSerial.h | 15 ++++++++ code/Arduino/connectors/USB.cpp | 5 +++ code/Arduino/connectors/USB.h | 10 ++++++ code/Arduino/trackPlatform.ino | 24 ++++++++++++- code/Arduino/trackPlatform.vcxproj | 4 +++ code/Arduino/trackPlatform.vcxproj.filters | 16 +++++++++ .../cxx-api/TrackPlatform_BasicManagement.cpp | 9 ++++- code/c++/cxx-app/main.cpp | 35 +++++++++++++++---- 13 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 code/Arduino/connectors/DebugSerial.cpp create mode 100644 code/Arduino/connectors/DebugSerial.h create mode 100644 code/Arduino/connectors/USB.cpp create mode 100644 code/Arduino/connectors/USB.h diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 469c23d..7ac3f42 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -45,6 +45,11 @@ const uint8_t Constants::countDistanceSensors = 5; const uint8_t Constants::countLineSensors = 5; const uint16_t Constants::minimalLineBound = 270; +/* Serial 1 (Debug serial, hardware)*/ +const uint8_t Constants::dbg_uart_RX = 52; +const uint8_t Constants::dbg_uart_TX = 53; +const uint8_t Constants::dbg_uart_speed = 9600; + Constants::Constants() { } diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index ec11485..ea6cb0b 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -41,6 +41,10 @@ class Constants static const uint8_t countDistanceSensors; static const uint8_t countLineSensors; static const uint16_t minimalLineBound; + + static const uint8_t dbg_uart_RX; + static const uint8_t dbg_uart_TX; + static const uint8_t dbg_uart_speed; Constants(); ~Constants(); diff --git a/code/Arduino/connectors/ConnectingDevice.cpp b/code/Arduino/connectors/ConnectingDevice.cpp index a87fa4b..86c5b34 100644 --- a/code/Arduino/connectors/ConnectingDevice.cpp +++ b/code/Arduino/connectors/ConnectingDevice.cpp @@ -1,11 +1,16 @@ #include "ConnectingDevice.h" #include "SoftwareSerial.h" +ConnectingDevice::ConnectingDevice(Stream* ptr) : device(ptr) +{ +} + ConnectingDevice::ConnectingDevice(int rx, int tx, int speed) { - device = new SoftwareSerial(rx, tx); - device->begin(speed); - device->listen(); + SoftwareSerial* serialPtr = new SoftwareSerial(rx, tx); + device = serialPtr; + serialPtr->begin(speed); + serialPtr->listen(); } void ConnectingDevice::send(String data) @@ -35,5 +40,4 @@ String ConnectingDevice::read() ConnectingDevice::~ConnectingDevice() { - delete device; } diff --git a/code/Arduino/connectors/ConnectingDevice.h b/code/Arduino/connectors/ConnectingDevice.h index c1a643b..2d16475 100644 --- a/code/Arduino/connectors/ConnectingDevice.h +++ b/code/Arduino/connectors/ConnectingDevice.h @@ -1,12 +1,13 @@ #pragma once -#include #include +#include class ConnectingDevice { protected: - SoftwareSerial *device; + explicit ConnectingDevice(Stream* ptr); + Stream *device; public: ConnectingDevice(int rx, int tx, int speed); bool isActive(); diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp new file mode 100644 index 0000000..7e95740 --- /dev/null +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -0,0 +1,21 @@ +#include "../Constants.h" +#include "DebugSerial.h" + +SoftwareSerial* DebugSerial::serial = DebugSerial::generateDbgSerial(); + +SoftwareSerial* DebugSerial::generateDbgSerial() +{ + SoftwareSerial* serialPtr = new SoftwareSerial(Constants::dbg_uart_RX, Constants::bluetooth_TX); + serialPtr->begin(Constants::dbg_uart_speed); + serialPtr->listen(); + return serialPtr; +} + +DebugSerial::DebugSerial(): ConnectingDevice(serial) +{ +} + +Stream* DebugSerial::getSerial() +{ + return serial; +} diff --git a/code/Arduino/connectors/DebugSerial.h b/code/Arduino/connectors/DebugSerial.h new file mode 100644 index 0000000..570b0a9 --- /dev/null +++ b/code/Arduino/connectors/DebugSerial.h @@ -0,0 +1,15 @@ +#pragma once +#include + +#include "ConnectingDevice.h" + +class DebugSerial : ConnectingDevice +{ + static SoftwareSerial* serial; + + static SoftwareSerial* generateDbgSerial(); +public: + DebugSerial(); + + static Stream* getSerial(); +}; diff --git a/code/Arduino/connectors/USB.cpp b/code/Arduino/connectors/USB.cpp new file mode 100644 index 0000000..fe61534 --- /dev/null +++ b/code/Arduino/connectors/USB.cpp @@ -0,0 +1,5 @@ +#include "USB.h" + +USB::USB() : ConnectingDevice(&Serial) +{ +} diff --git a/code/Arduino/connectors/USB.h b/code/Arduino/connectors/USB.h new file mode 100644 index 0000000..2521bc4 --- /dev/null +++ b/code/Arduino/connectors/USB.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "ConnectingDevice.h" + +class USB : public ConnectingDevice +{ +public: + USB(); +}; diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 0df6613..e67ffdc 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -3,32 +3,54 @@ #include "connectors/ConnectingDevice.h" #include "connectors/Bluetooth.h" #include "CommandsController.h" +#include "connectors/USB.h" +#include "connectors/DebugSerial.h" Constants constants; Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bluetooth_serial_speed); WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); +USB usb; ConnectingDevice *device; CommandsController controller; +Stream* debugSerial = DebugSerial::getSerial(); bool connected = false; void setup() { + debugSerial->println("Arduino was started"); while (!connected) { if (bluetooth.isActive()) { connected = true; device = &bluetooth; + debugSerial->println("Bluetooth"); } else if (wifi.isActive()) { connected = true; device = &wifi; + debugSerial->println("Wifi"); + } + else if (usb.isActive()) { + connected = true; + device = &usb; + debugSerial->println("USB"); } } } void loop() -{ +{ delay(100); //for sending commands from mobile String command = device->read(); controller.handle(device, command); + + //debug + for (int i = 0; i < command.length(); ++i) + { + debugSerial->printf("%02X ", command[i]); + } + if (command.length() > 0) + { + debugSerial->println(""); + } } diff --git a/code/Arduino/trackPlatform.vcxproj b/code/Arduino/trackPlatform.vcxproj index 2dbc857..706f70d 100644 --- a/code/Arduino/trackPlatform.vcxproj +++ b/code/Arduino/trackPlatform.vcxproj @@ -89,6 +89,8 @@ + + @@ -103,6 +105,8 @@ + + diff --git a/code/Arduino/trackPlatform.vcxproj.filters b/code/Arduino/trackPlatform.vcxproj.filters index 8fd3b0f..e70ba40 100644 --- a/code/Arduino/trackPlatform.vcxproj.filters +++ b/code/Arduino/trackPlatform.vcxproj.filters @@ -18,18 +18,22 @@ {59c1c582-bece-4678-8894-1f186df97c5b} + h;hh;hpp;hxx;hm;inl;inc;xsd {4d8737a4-6736-4d31-803f-f0f98e318ba5} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {8e5e8e86-61de-4400-bc87-9882d23f80b0} {5a05d265-b32e-4399-9fbd-931b3b0be584} + h;hh;hpp;hxx;hm;inl;inc;xsd {0331c73c-5716-43bd-a435-2ed6e0b5999b} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx @@ -75,6 +79,12 @@ peripheral\header + + connectors\header + + + connectors + @@ -104,6 +114,12 @@ peripheral\source + + connectors\source + + + connectors + diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index e832516..755dfa4 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -22,7 +22,14 @@ std::vector TrackPlatform_BasicManagement::parseStringToArray(std::str size_t posToNextValue = 0; do { - distancies.push_back(std::stoul(s, &posToNextValue)); + try + { + distancies.push_back(std::stoul(s, &posToNextValue)); + } + catch(...) + { + return distancies; + } stringOldLen = s.length(); s = s.substr(posToNextValue + sizeof delimiter); } while ((s != "") && (stringOldLen > s.length())); diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 07f3486..0a1c952 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -27,18 +27,22 @@ int main(int argc, char* argv[]) bool isExit = false; while (!isExit) { + std::cout << "Input command, please (0 to help): "; auto c = _getche(); + std::cout << std::endl; switch (c) { case '0': - std::cout << "0: help"; - std::cout << "q: quit"; - std::cout << "w: move forward"; - std::cout << "s: move back"; - std::cout << "a: turn left (anticlockwise)"; - std::cout << "d: turn right (clockwise)"; - std::cout << " : stop"; + std::cout << "0: help" << std::endl; + std::cout << "q: quit" << std::endl; + std::cout << "w: move forward" << std::endl; + std::cout << "s: move back" << std::endl; + std::cout << "a: turn left (anticlockwise)" << std::endl; + std::cout << "d: turn right (clockwise)" << std::endl; + std::cout << " : stop" << std::endl; + std::cout << "r: get all line values" << std::endl; + std::cout << "e: get fixed line value" << std::endl; break; case 'q': isExit = true; @@ -58,6 +62,23 @@ int main(int argc, char* argv[]) case ' ': trackPlatform.moveStopAll(); break; + case 'r': + { + auto arr = trackPlatform.sensorLineGetAllValues(); + for (auto a : arr) + { + std::cout << a << std::endl; + } + break; + } + case 'e': + { + std::cout << "Input num: "; + int a; + std::cin >> a; + std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a); + break; + } default: break; } } From 8c778891eff7ccbb91017a1654242831349d04b9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 29 Jul 2017 14:32:32 +0300 Subject: [PATCH 016/336] =?UTF-8?q?*=20ConnectiongDevice:=20=D0=B2=D1=81?= =?UTF-8?q?=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D1=8E=D1=82=20virtual=20=D0=BC=D0=BE=D0=B4=D0=B8=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D1=80=20*=20DebugSerial:=20fix?= =?UTF-8?q?=20=D0=BD=D0=B0=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B8=20=D0=BF=D0=BE=D1=80=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?*=20USB:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20TODO=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=B0=D1=87=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=D0=BD=D0=BE=D0=B9=20=D0=B8=D0=BD=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20*=20Constant?= =?UTF-8?q?s:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20USB=20*=20trackPlatform.ino:=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7?= =?UTF-8?q?=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7?= =?UTF-8?q?=20=D1=81=D0=B2=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D0=BE=D0=B4=D1=8B?= =?UTF-8?q?=20(=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D1=8E?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 15 ++++-- code/Arduino/Constants.h | 12 +++-- code/Arduino/connectors/ConnectingDevice.cpp | 6 +-- code/Arduino/connectors/ConnectingDevice.h | 6 +-- code/Arduino/connectors/DebugSerial.cpp | 7 ++- code/Arduino/connectors/DebugSerial.h | 4 +- code/Arduino/connectors/USB.cpp | 1 + code/Arduino/trackPlatform.ino | 52 +++++++++++++++++++- 8 files changed, 84 insertions(+), 19 deletions(-) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 7ac3f42..b03009c 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -10,6 +10,16 @@ const uint8_t Constants::wifi_RX = 30; const uint8_t Constants::wifi_TX = 31; const uint32_t Constants::wifi_serial_speed = 9600; +/* USB */ +// const uint8_t Constants::usb_RX = 0; +// const uint8_t Constants::usb_TX = 1; +const uint32_t Constants::usb_serial_speed = 9600; + +/* Debug serial */ +const uint8_t Constants::dbg_uart_RX = 52; +const uint8_t Constants::dbg_uart_TX = 53; +const uint32_t Constants::dbg_uart_speed = 9600; + /* Movement controller (L298N) */ const uint8_t Constants::left_engine_enable = A8; const uint8_t Constants::left_engine_straight_pin = 30; @@ -45,11 +55,6 @@ const uint8_t Constants::countDistanceSensors = 5; const uint8_t Constants::countLineSensors = 5; const uint16_t Constants::minimalLineBound = 270; -/* Serial 1 (Debug serial, hardware)*/ -const uint8_t Constants::dbg_uart_RX = 52; -const uint8_t Constants::dbg_uart_TX = 53; -const uint8_t Constants::dbg_uart_speed = 9600; - Constants::Constants() { } diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index ea6cb0b..610ead8 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -12,6 +12,14 @@ class Constants static const uint8_t wifi_TX; static const uint32_t wifi_serial_speed; + // static const uint8_t usb_RX; + // static const uint8_t usb_TX; + static const uint32_t usb_serial_speed; + + static const uint8_t dbg_uart_RX; + static const uint8_t dbg_uart_TX; + static const uint32_t dbg_uart_speed; + static const uint8_t left_engine_enable; static const uint8_t left_engine_straight_pin; static const uint8_t left_engine_reverse_pin; @@ -41,10 +49,6 @@ class Constants static const uint8_t countDistanceSensors; static const uint8_t countLineSensors; static const uint16_t minimalLineBound; - - static const uint8_t dbg_uart_RX; - static const uint8_t dbg_uart_TX; - static const uint8_t dbg_uart_speed; Constants(); ~Constants(); diff --git a/code/Arduino/connectors/ConnectingDevice.cpp b/code/Arduino/connectors/ConnectingDevice.cpp index 86c5b34..60cf8f3 100644 --- a/code/Arduino/connectors/ConnectingDevice.cpp +++ b/code/Arduino/connectors/ConnectingDevice.cpp @@ -13,12 +13,12 @@ ConnectingDevice::ConnectingDevice(int rx, int tx, int speed) serialPtr->listen(); } -void ConnectingDevice::send(String data) +void ConnectingDevice::send(String data) { - this->device->println(data); + device->print(data); } -bool ConnectingDevice::isActive() +bool ConnectingDevice::isActive() { if ((*device).available()) { return true; diff --git a/code/Arduino/connectors/ConnectingDevice.h b/code/Arduino/connectors/ConnectingDevice.h index 2d16475..a5752e6 100644 --- a/code/Arduino/connectors/ConnectingDevice.h +++ b/code/Arduino/connectors/ConnectingDevice.h @@ -10,9 +10,9 @@ class ConnectingDevice Stream *device; public: ConnectingDevice(int rx, int tx, int speed); - bool isActive(); - String read(); - void send(String data); + virtual bool isActive(); + virtual String read(); + virtual void send(String data); virtual ~ConnectingDevice(); }; diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp index 7e95740..ea624cb 100644 --- a/code/Arduino/connectors/DebugSerial.cpp +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -5,7 +5,7 @@ SoftwareSerial* DebugSerial::serial = DebugSerial::generateDbgSerial(); SoftwareSerial* DebugSerial::generateDbgSerial() { - SoftwareSerial* serialPtr = new SoftwareSerial(Constants::dbg_uart_RX, Constants::bluetooth_TX); + SoftwareSerial* serialPtr = new SoftwareSerial(Constants::dbg_uart_RX, Constants::dbg_uart_TX); serialPtr->begin(Constants::dbg_uart_speed); serialPtr->listen(); return serialPtr; @@ -19,3 +19,8 @@ Stream* DebugSerial::getSerial() { return serial; } + +void DebugSerial::send(String data) +{ + device->println(data); +} diff --git a/code/Arduino/connectors/DebugSerial.h b/code/Arduino/connectors/DebugSerial.h index 570b0a9..77c6025 100644 --- a/code/Arduino/connectors/DebugSerial.h +++ b/code/Arduino/connectors/DebugSerial.h @@ -3,7 +3,7 @@ #include "ConnectingDevice.h" -class DebugSerial : ConnectingDevice +class DebugSerial : public ConnectingDevice { static SoftwareSerial* serial; @@ -12,4 +12,6 @@ class DebugSerial : ConnectingDevice DebugSerial(); static Stream* getSerial(); + + void send(String data) override; }; diff --git a/code/Arduino/connectors/USB.cpp b/code/Arduino/connectors/USB.cpp index fe61534..dd9ca8f 100644 --- a/code/Arduino/connectors/USB.cpp +++ b/code/Arduino/connectors/USB.cpp @@ -2,4 +2,5 @@ USB::USB() : ConnectingDevice(&Serial) { + //TODO: start serial on speed Constants::usb_serial_speed in `setup` loop } diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index e67ffdc..171cf2a 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -6,11 +6,22 @@ #include "connectors/USB.h" #include "connectors/DebugSerial.h" +#define DIOD_DEBUG + +#ifdef DIOD_DEBUG +void diodInit(); +void on43(); +void off43(); +void on45(); +void off45(); + +#endif /* DIOD_DEBUG */ + Constants constants; Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bluetooth_serial_speed); WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); USB usb; -ConnectingDevice *device; +ConnectingDevice *device = nullptr; CommandsController controller; Stream* debugSerial = DebugSerial::getSerial(); @@ -18,7 +29,14 @@ bool connected = false; void setup() { +#ifdef DIOD_DEBUG + diodInit(); +#endif /* DIOD_DEBUG */ + + Serial.begin(Constants::usb_serial_speed); + debugSerial->println("Arduino was started"); + while (!connected) { if (bluetooth.isActive()) { connected = true; @@ -40,7 +58,7 @@ void setup() void loop() { - delay(100); //for sending commands from mobile + delay(100); //for sending commands from mobile String command = device->read(); controller.handle(device, command); @@ -54,3 +72,33 @@ void loop() debugSerial->println(""); } } + +#ifdef DIOD_DEBUG + +void diodInit() +{ + pinMode(43, OUTPUT); + pinMode(45, OUTPUT); +} + +void on43() +{ + digitalWrite(43, HIGH); +} + +void off43() +{ + digitalWrite(43, LOW); +} + +void on45() +{ + digitalWrite(45, HIGH); +} + +void off45() +{ + digitalWrite(45, LOW); +} + +#endif /* DIOD_DEBUG */ From 73057d880493cc17da26c0bd25f8bb3a9b22e771 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 29 Jul 2017 15:49:21 +0300 Subject: [PATCH 017/336] =?UTF-8?q?*=20cxx-app:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=D0=B6=D0=BA=D0=B0=20=D0=B4=D0=B0=D1=82=D1=87=D0=B8=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2=20=D1=80=D0=B0=D1=81=D1=81=D1=82=D0=BE=D1=8F=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/main.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 0a1c952..8c647dc 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -43,6 +43,8 @@ int main(int argc, char* argv[]) std::cout << " : stop" << std::endl; std::cout << "r: get all line values" << std::endl; std::cout << "e: get fixed line value" << std::endl; + std::cout << "t: get all distance values" << std::endl; + std::cout << "y: get fixed distance value" << std::endl; break; case 'q': isExit = true; @@ -76,7 +78,24 @@ int main(int argc, char* argv[]) std::cout << "Input num: "; int a; std::cin >> a; - std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a); + std::cout << "Value: " << trackPlatform.sensorLineGetValue(a) << std::endl; + break; + } + case 't': + { + auto arr = trackPlatform.sensorDistanceGetAllValues(); + for (auto a : arr) + { + std::cout << a << std::endl; + } + break; + } + case 'y': + { + std::cout << "Input num: "; + int a; + std::cin >> a; + std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a) << std::endl; break; } default: break; From 5b272edf64eeb1b6d672e11399d1959e62bdc11d Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 30 Jul 2017 11:47:01 +0300 Subject: [PATCH 018/336] =?UTF-8?q?*=20Arduino:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BD=D0=B5=D0=BC=D0=BD=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BB=D0=B0=D0=B4=D0=BE=D1=87=D0=BD=D0=BE=D0=B9=20=D0=B8?= =?UTF-8?q?=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/peripheral/SensorsController.cpp | 11 +++++++---- code/Arduino/trackPlatform.ino | 7 ++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index c1b73df..08aff48 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -1,4 +1,5 @@ #include "../CommandsEnum.h" +#include "../connectors/DebugSerial.h" #include "SensorsController.h" SensorsController::SensorsController() @@ -73,7 +74,7 @@ void SensorsController::chooseLineSensor(int number) { digitalWrite(constants.line_sensor_b_pin, LOW); digitalWrite(constants.line_sensor_c_pin, LOW); break; - default: + default: break; } } @@ -103,12 +104,12 @@ void SensorsController::chooseDistanceSensor(int number) { digitalWrite(constants.distance_sensor_b_pin, HIGH); digitalWrite(constants.distance_sensor_c_pin, HIGH); break; - case 3: + case 3: digitalWrite(constants.distance_sensor_a_pin, LOW); digitalWrite(constants.distance_sensor_b_pin, LOW); digitalWrite(constants.distance_sensor_c_pin, HIGH); break; - case 4: + case 4: digitalWrite(constants.distance_sensor_a_pin, HIGH); digitalWrite(constants.distance_sensor_b_pin, LOW); digitalWrite(constants.distance_sensor_c_pin, HIGH); @@ -118,7 +119,7 @@ void SensorsController::chooseDistanceSensor(int number) { digitalWrite(constants.distance_sensor_b_pin, HIGH); digitalWrite(constants.distance_sensor_c_pin, HIGH); break; - default: + default: break; } } @@ -127,8 +128,10 @@ void SensorsController::chooseDistanceSensor(int number) { int SensorsController::getDistance(int number) { chooseDistanceSensor(number); float volts = analogRead(constants.distance_sensor_read_pin); + DebugSerial::getSerial()->printf("Distance volts: %d\n", (int)volts); if (volts == 0) { + DebugSerial::getSerial()->print("Distance volts were 0"); return -1; //TODO: crutch } float distance = (6762 / (volts)) - 4; diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 171cf2a..84f8bb8 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -60,9 +60,12 @@ void loop() { delay(100); //for sending commands from mobile String command = device->read(); - controller.handle(device, command); //debug + if (command.length() > 0) + { + debugSerial->print("Command: "); + } for (int i = 0; i < command.length(); ++i) { debugSerial->printf("%02X ", command[i]); @@ -71,6 +74,8 @@ void loop() { debugSerial->println(""); } + + controller.handle(device, command); } #ifdef DIOD_DEBUG From 8b4c2920447ff7e80c76becd38c16f0b8a5b41fe Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 31 Jul 2017 23:25:47 +0300 Subject: [PATCH 019/336] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B0=20=D1=81=D1=82=D0=BE=D0=BF-=D1=81=D0=B8?= =?UTF-8?q?=D0=BC=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cxx-api: добавлена отправка стоп-символов на плату * cxx-app: изменен com-порт по умолчанию для отладки --- .../cxx-api/TrackPlatform_BasicManagement.cpp | 16 +++++++++++++--- code/c++/cxx-api/TrackPlatform_BasicManagement.h | 3 +++ code/c++/cxx-app/main.cpp | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 755dfa4..28daf94 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -2,17 +2,27 @@ void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) const { - connector->write(static_cast(movementControllerID) + additionalInfo); + sendOneCommand(static_cast(movementControllerID) + additionalInfo); } void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInfo) const { - connector->write(static_cast(sensorsControllerID) + additionalInfo); + sendOneCommand(static_cast(sensorsControllerID) + additionalInfo); } void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) const { - connector->write(static_cast(servoControllerID) + additionalInfo); + sendOneCommand(static_cast(servoControllerID) + additionalInfo); +} + +void TrackPlatform_BasicManagement::sendOneCommand(const std::string& info) const +{ + if (!connector) + { + throw std::exception("Bad memory"); + } + + connector->write(info + stopSymbol); } std::vector TrackPlatform_BasicManagement::parseStringToArray(std::string s) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index b5258bb..a6fed73 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -13,12 +13,15 @@ class TrackPlatform_BasicManagement static const uint8_t minSpeed = 0; static const uint8_t maxSpeed = 255; static const char delimiter = ';'; + static const char stopSymbol = '|'; protected: void sendMove(const std::string& additionalInfo) const; void sendSensors(const std::string& additionalInfo) const; void sendServo(const std::string& additionalInfo) const; + void sendOneCommand(const std::string& info) const; + static std::vector parseStringToArray(std::string s); TrackPlatform_BasicConnector* getConnector() const; diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 8c647dc..d4cef88 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -9,7 +9,7 @@ int main(int argc, char* argv[]) { - std::string rx = "COM10", tx = "COM10"; + std::string rx = "COM13", tx = "COM13"; uint32_t baudrate = 9600U; /*std::cout << "rx" << std::endl; From 76f3892a77c4eba36cdd4263ab67b3aa62f6e735 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 31 Jul 2017 23:41:08 +0300 Subject: [PATCH 020/336] =?UTF-8?q?=D0=9D=D0=B5=D1=81=D0=BA=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=BA=D0=BE=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Добавлены print, println, printHex and printlnHex методы для отладки * Добавлен символ-разделитель и время ожидания строки. * Поправлен вывод уведомления о попытке деления на 0 в отладочную консоль. --- code/Arduino/Constants.cpp | 2 ++ code/Arduino/Constants.h | 2 ++ code/Arduino/connectors/ConnectingDevice.cpp | 19 ++++------ code/Arduino/connectors/DebugSerial.cpp | 24 +++++++++++++ code/Arduino/connectors/DebugSerial.h | 29 +++++++++++++++ code/Arduino/peripheral/SensorsController.cpp | 2 +- code/Arduino/trackPlatform.ino | 35 ++++++++----------- 7 files changed, 79 insertions(+), 34 deletions(-) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index b03009c..a06604b 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -45,6 +45,8 @@ const uint8_t Constants::servo_horizontal_pin = 34; const uint8_t Constants::servo_vertical_pin = 35; const char Constants::commands_delimetr = ';'; +const char Constants::commands_stop_symbol = '|'; +const uint32_t Constants::commands_waitTime = 100; /* Class constants */ const uint8_t Constants::min_speed = 0; diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index 610ead8..851a78f 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -41,6 +41,8 @@ class Constants static const uint8_t servo_vertical_pin; static const char commands_delimetr; + static const char commands_stop_symbol; + static const uint32_t commands_waitTime; static const uint8_t min_speed; static const uint8_t max_speed; diff --git a/code/Arduino/connectors/ConnectingDevice.cpp b/code/Arduino/connectors/ConnectingDevice.cpp index 60cf8f3..573141b 100644 --- a/code/Arduino/connectors/ConnectingDevice.cpp +++ b/code/Arduino/connectors/ConnectingDevice.cpp @@ -1,16 +1,20 @@ +#include "../Constants.h" #include "ConnectingDevice.h" #include "SoftwareSerial.h" ConnectingDevice::ConnectingDevice(Stream* ptr) : device(ptr) { + device->setTimeout(Constants::commands_waitTime); } ConnectingDevice::ConnectingDevice(int rx, int tx, int speed) { SoftwareSerial* serialPtr = new SoftwareSerial(rx, tx); - device = serialPtr; serialPtr->begin(speed); serialPtr->listen(); + + device = serialPtr; + device->setTimeout(Constants::commands_waitTime); } void ConnectingDevice::send(String data) @@ -20,21 +24,12 @@ void ConnectingDevice::send(String data) bool ConnectingDevice::isActive() { - if ((*device).available()) { - return true; - } - return false; + return device->available(); } String ConnectingDevice::read() { - String command = ""; - - while ((*device).available()) { - char code = (*device).read(); - command += code; - } - return command; + return device->readStringUntil(Constants::commands_stop_symbol); } diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp index ea624cb..97ca371 100644 --- a/code/Arduino/connectors/DebugSerial.cpp +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -24,3 +24,27 @@ void DebugSerial::send(String data) { device->println(data); } + +void DebugSerial::print(String data) +{ + device->print(data); +} + +void DebugSerial::println(String data) +{ + device->println(data); +} + +void DebugSerial::printHex(String data) +{ + for (int i = 0; i < data.length(); ++i) + { + device->printf("%02X ", data[i]); + } +} + +void DebugSerial::printlnHex(String data) +{ + printHex(data); + device->println(""); +} diff --git a/code/Arduino/connectors/DebugSerial.h b/code/Arduino/connectors/DebugSerial.h index 77c6025..d834c75 100644 --- a/code/Arduino/connectors/DebugSerial.h +++ b/code/Arduino/connectors/DebugSerial.h @@ -13,5 +13,34 @@ class DebugSerial : public ConnectingDevice static Stream* getSerial(); + /** + * @brief println(String) duplicate + * + * @param data String to send + */ void send(String data) override; + /** + * @brief Prints data string to debug console + * + * @param data String to print + */ + void print(String data); + /** + * @brief Prints data to debug console and adds newline symbol in the end + * + * @param data String to print + */ + void println(String data); + /** + * @brief Prints data in hex view (with space delimiters) to debug console + * + * @param data String to print + */ + void printHex(String data); + /** + * @brief Prints data in hex view (with space delimiters) to debug console and prints newline symbol at the end + * + * @param data String to print + */ + void printlnHex(String data); }; diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index 08aff48..fca83c1 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -131,7 +131,7 @@ int SensorsController::getDistance(int number) { DebugSerial::getSerial()->printf("Distance volts: %d\n", (int)volts); if (volts == 0) { - DebugSerial::getSerial()->print("Distance volts were 0"); + DebugSerial::getSerial()->println("Distance volts were 0"); return -1; //TODO: crutch } float distance = (6762 / (volts)) - 4; diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 84f8bb8..be51a0b 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -23,7 +23,7 @@ WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); USB usb; ConnectingDevice *device = nullptr; CommandsController controller; -Stream* debugSerial = DebugSerial::getSerial(); +DebugSerial debugSerial; bool connected = false; @@ -35,47 +35,40 @@ void setup() Serial.begin(Constants::usb_serial_speed); - debugSerial->println("Arduino was started"); + debugSerial.println("Arduino was started"); while (!connected) { if (bluetooth.isActive()) { connected = true; device = &bluetooth; - debugSerial->println("Bluetooth"); + debugSerial.println("Bluetooth"); } else if (wifi.isActive()) { connected = true; device = &wifi; - debugSerial->println("Wifi"); + debugSerial.println("Wifi"); } else if (usb.isActive()) { connected = true; device = &usb; - debugSerial->println("USB"); + debugSerial.println("USB"); } } } void loop() { - delay(100); //for sending commands from mobile - String command = device->read(); - - //debug - if (command.length() > 0) - { - debugSerial->print("Command: "); - } - for (int i = 0; i < command.length(); ++i) - { - debugSerial->printf("%02X ", command[i]); - } - if (command.length() > 0) + while (device->isActive()) { - debugSerial->println(""); - } + String command = device->read(); - controller.handle(device, command); + //debug + debugSerial.print("Command: "); + debugSerial.printlnHex(command); + + controller.handle(device, command); + } + delay(100); //for sending commands from mobile (not required) } #ifdef DIOD_DEBUG From 0cae0984035845463def3051bd58bafc73ac496f Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 2 Aug 2017 15:23:02 +0300 Subject: [PATCH 021/336] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D1=82=D0=B0=D0=B9=D0=BC=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/trackPlatform.vcxproj | 2 + code/Arduino/trackPlatform.vcxproj.filters | 17 +++++ code/Arduino/utils/Timer.cpp | 79 ++++++++++++++++++++++ code/Arduino/utils/Timer.h | 68 +++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 code/Arduino/utils/Timer.cpp create mode 100644 code/Arduino/utils/Timer.h diff --git a/code/Arduino/trackPlatform.vcxproj b/code/Arduino/trackPlatform.vcxproj index 706f70d..67a6a42 100644 --- a/code/Arduino/trackPlatform.vcxproj +++ b/code/Arduino/trackPlatform.vcxproj @@ -98,6 +98,7 @@ + @@ -113,6 +114,7 @@ + diff --git a/code/Arduino/trackPlatform.vcxproj.filters b/code/Arduino/trackPlatform.vcxproj.filters index e70ba40..4d322cd 100644 --- a/code/Arduino/trackPlatform.vcxproj.filters +++ b/code/Arduino/trackPlatform.vcxproj.filters @@ -35,6 +35,17 @@ {0331c73c-5716-43bd-a435-2ed6e0b5999b} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + {7492051d-9540-415b-b623-46b80c5f0577} + + + {9ab2f623-714d-45f8-bddf-f73617228341} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {764c9bee-87ce-4cfc-9000-81d3bd8a32a0} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + @@ -85,6 +96,9 @@ connectors + + utils\header + @@ -120,6 +134,9 @@ connectors + + utils\source + diff --git a/code/Arduino/utils/Timer.cpp b/code/Arduino/utils/Timer.cpp new file mode 100644 index 0000000..b9450e9 --- /dev/null +++ b/code/Arduino/utils/Timer.cpp @@ -0,0 +1,79 @@ +#include "Timer.h" + +void Timer::updateState() +{ +} + +Timer::Timer(uint32_t timeToSet): startTime_ms(0), timeToSet_ms(timeToSet), passedTime_ms(0), state(timerState_stopped) +{ +} + +/* + * switch(state) + { + case timerState_none: { + break; + } + case timerState_started: { + break; + } + case timerState_paused: { + break; + } + case timerState_stopped: { + break; + } + case timerState_finished: { + break; + } + default: { break;} + } + */ + +void Timer::startOrResume() +{ + switch(state) + { + case timerState_paused: { + startTime_ms = millis() - passedTime_ms; + passedTime_ms = 0; + state = timerState_started; + break; + } + case timerState_stopped: { + startTime_ms = millis(); + state = timerState_started; + break; + } + default: { break; } + } +} + +void Timer::stop() +{ +} + +void Timer::reset() +{ +} + +void Timer::pause() +{ +} + +void Timer::setSetTime(uint32_t timeToSet) +{ + timeToSet_ms = timeToSet; + updateState(); +} + +TimerState Timer::getState() +{ + updateState(); + return state; +} + +bool Timer::isFinished() +{ + return (getState() == timerState_finished); +} diff --git a/code/Arduino/utils/Timer.h b/code/Arduino/utils/Timer.h new file mode 100644 index 0000000..088e738 --- /dev/null +++ b/code/Arduino/utils/Timer.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +enum TimerState { + timerState_none, + timerState_started, + timerState_paused, + timerState_stopped, + timerState_finished +}; + +class Timer +{ + uint32_t startTime_ms; + uint32_t timeToSet_ms; + uint32_t passedTime_ms; //used only to pause timer + TimerState state; + +protected: + /** + * @brief Updates current state information + */ + void updateState(); + +public: + /** + * @brief Creates timer and sets + * + * @param timeToSet Time to set timer in milliseconds + */ + Timer(uint32_t timeToSet); + + /** + * @brief Starts or resumes setting timer + */ + void startOrResume(); + /** + * @brief Pause setting timer and resets time to beginning value + * @warning Cannot stop finished timer (it will not change state) + */ + void stop(); + /** + * @brief Resets timer (resets time to require to set timer to beginnig value, but not pause it) + * @warning If timer was finished before, it will be in stopped state + */ + void reset(); + /** + * @brief Pause setting timer + */ + void pause(); + /** + * @brief Sets time to set to timer, but not reset timer (reset it manual, if require) + * + * @param timeToSet New time to set timer in milliseconds + */ + void setSetTime(uint32_t timeToSet); + /** + * @brief Checks timeout and gets timer state + * @return State of timer + */ + TimerState getState(); + /** + * @brief Checks timeout and gets is timer setted + * @return true, if timer setted/finished (time were passed), else false + */ + bool isFinished(); +}; From 5fa29fd62f1e02ff83e5a8f909445420f661d634 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 3 Aug 2017 21:36:26 +0300 Subject: [PATCH 022/336] =?UTF-8?q?*=20=D0=94=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BD=20=D1=82=D0=B0=D0=B9=D0=BC=D0=B5=D1=80=20*=20?= =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D1=8B=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D0=B0=20=D0=B8=20=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=81=D0=BE=D0=B5?= =?UTF-8?q?=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20(=D0=BD=D0=B5?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BD=D0=B0=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20=D0=B4=D0=BB=D1=8F=20cxx-api)?= =?UTF-8?q?=20*=20=D0=9D=D0=B0=D1=87=D0=B0=D1=82=D0=B0=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/CommandsEnum.h | 16 ++++- code/Arduino/trackPlatform.ino | 44 +++++++++---- code/Arduino/utils/Timer.cpp | 64 ++++++++++++------- code/Arduino/utils/Timer.h | 4 +- code/c++/cxx-api/CommandsEnum.h | 16 ++++- code/c++/cxx-api/ConnectionModes.h | 3 +- .../cxx-api/TrackPlatform_BasicConnector.cpp | 14 +++- .../cxx-api/TrackPlatform_BasicConnector.h | 3 + code/c++/cxx-api/TrackPlatform_Manager.cpp | 3 + 9 files changed, 126 insertions(+), 41 deletions(-) diff --git a/code/Arduino/CommandsEnum.h b/code/Arduino/CommandsEnum.h index f5501c8..f781da2 100644 --- a/code/Arduino/CommandsEnum.h +++ b/code/Arduino/CommandsEnum.h @@ -4,7 +4,8 @@ enum ControllerEnum { movementControllerID = '\001', sensorsControllerID = '\002', - servoControllerID = '\003' + servoControllerID = '\003', + communicationControllerID = '\004', }; enum SensorsEnum { @@ -44,4 +45,17 @@ enum ServoCommands { get_coodrinates = '\004', //get current angels of horizontal and vertical servos }; +enum CommunicationCommands { + startCommunicationCommand = 1, //starting communication command + stopCommunicationCommand = 2, //stopping communication command +}; + +/** + * @brief Describes trackPlatform API to working + * @warning Each API must be described in DeviceManager handler + */ +enum StartCommands { + startBasicAPI = 1, //default API v1 +}; + #endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index be51a0b..b8d40c4 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -5,6 +5,7 @@ #include "CommandsController.h" #include "connectors/USB.h" #include "connectors/DebugSerial.h" +#include "CommandsEnum.h" #define DIOD_DEBUG @@ -25,35 +26,45 @@ ConnectingDevice *device = nullptr; CommandsController controller; DebugSerial debugSerial; +char connectCommand[] = { communicationControllerID, startCommunicationCommand, startBasicAPI }; +char disconnectCommand[] = {communicationControllerID, stopCommunicationCommand }; + bool connected = false; -void setup() +void selectDevice() { -#ifdef DIOD_DEBUG - diodInit(); -#endif /* DIOD_DEBUG */ - - Serial.begin(Constants::usb_serial_speed); - - debugSerial.println("Arduino was started"); - + debugSerial.println("Arduino tries to found a manager"); while (!connected) { - if (bluetooth.isActive()) { + if (bluetooth.isActive() && bluetooth.read() == connectCommand) { connected = true; device = &bluetooth; debugSerial.println("Bluetooth"); } - else if (wifi.isActive()) { + else if (wifi.isActive() && wifi.read() == connectCommand) { connected = true; device = &wifi; debugSerial.println("Wifi"); } - else if (usb.isActive()) { + else if (usb.isActive() && usb.read() == connectCommand) { connected = true; device = &usb; debugSerial.println("USB"); } } + debugSerial.println("Arduino found a manager"); +} + +void setup() +{ +#ifdef DIOD_DEBUG + diodInit(); +#endif /* DIOD_DEBUG */ + + Serial.begin(Constants::usb_serial_speed); + + debugSerial.println("Arduino was started"); + + selectDevice(); } void loop() @@ -66,7 +77,14 @@ void loop() debugSerial.print("Command: "); debugSerial.printlnHex(command); - controller.handle(device, command); + if (command == disconnectCommand) + { + selectDevice(); + } + else + { + controller.handle(device, command); + } } delay(100); //for sending commands from mobile (not required) } diff --git a/code/Arduino/utils/Timer.cpp b/code/Arduino/utils/Timer.cpp index b9450e9..44bcc8d 100644 --- a/code/Arduino/utils/Timer.cpp +++ b/code/Arduino/utils/Timer.cpp @@ -2,34 +2,20 @@ void Timer::updateState() { + if (state == timerState_started) + { + auto current_ms = millis(); + if (static_cast(current_ms - startTime_ms) >= timeToSet_ms) + { + state = timerState_finished; + } + } } Timer::Timer(uint32_t timeToSet): startTime_ms(0), timeToSet_ms(timeToSet), passedTime_ms(0), state(timerState_stopped) { } -/* - * switch(state) - { - case timerState_none: { - break; - } - case timerState_started: { - break; - } - case timerState_paused: { - break; - } - case timerState_stopped: { - break; - } - case timerState_finished: { - break; - } - default: { break;} - } - */ - void Timer::startOrResume() { switch(state) @@ -51,14 +37,48 @@ void Timer::startOrResume() void Timer::stop() { + switch (state) + { + case timerState_started: + case timerState_paused: { + state = timerState_stopped; + break; + } + default: { break; } + } } void Timer::reset() { + switch (state) + { + case timerState_started: { + startTime_ms = millis(); + break; + } + case timerState_paused: { + passedTime_ms = 0; + break; + } + case timerState_finished: { + state = timerState_stopped; + break; + } + default: { break; } + } } void Timer::pause() { + switch (state) + { + case timerState_started: { + passedTime_ms = millis() - startTime_ms; + state = timerState_paused; + break; + } + default: { break; } + } } void Timer::setSetTime(uint32_t timeToSet) diff --git a/code/Arduino/utils/Timer.h b/code/Arduino/utils/Timer.h index 088e738..49f55a7 100644 --- a/code/Arduino/utils/Timer.h +++ b/code/Arduino/utils/Timer.h @@ -36,12 +36,12 @@ class Timer */ void startOrResume(); /** - * @brief Pause setting timer and resets time to beginning value + * @brief Stop setting timer and resets time to beginning value * @warning Cannot stop finished timer (it will not change state) */ void stop(); /** - * @brief Resets timer (resets time to require to set timer to beginnig value, but not pause it) + * @brief Resets timer (resets time to require to set timer to beginnig value, but not pause/stop it) * @warning If timer was finished before, it will be in stopped state */ void reset(); diff --git a/code/c++/cxx-api/CommandsEnum.h b/code/c++/cxx-api/CommandsEnum.h index f5501c8..f781da2 100644 --- a/code/c++/cxx-api/CommandsEnum.h +++ b/code/c++/cxx-api/CommandsEnum.h @@ -4,7 +4,8 @@ enum ControllerEnum { movementControllerID = '\001', sensorsControllerID = '\002', - servoControllerID = '\003' + servoControllerID = '\003', + communicationControllerID = '\004', }; enum SensorsEnum { @@ -44,4 +45,17 @@ enum ServoCommands { get_coodrinates = '\004', //get current angels of horizontal and vertical servos }; +enum CommunicationCommands { + startCommunicationCommand = 1, //starting communication command + stopCommunicationCommand = 2, //stopping communication command +}; + +/** + * @brief Describes trackPlatform API to working + * @warning Each API must be described in DeviceManager handler + */ +enum StartCommands { + startBasicAPI = 1, //default API v1 +}; + #endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/c++/cxx-api/ConnectionModes.h b/code/c++/cxx-api/ConnectionModes.h index e6312d5..edfebb6 100644 --- a/code/c++/cxx-api/ConnectionModes.h +++ b/code/c++/cxx-api/ConnectionModes.h @@ -3,7 +3,8 @@ enum ConnectionModes { - bluetooth + USB, + bluetooth, }; #endif /* _CONNECTION_MODES_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index df6c986..7b828d1 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -1,4 +1,16 @@ -#include "TrackPlatform_BasicConnector.h" +#include "CommandsEnum.h" +#include "TrackPlatform_BasicConnector.h" + +void TrackPlatform_BasicConnector::sendStartCommand() +{ + std::string command = std::string() + (char)communicationControllerID + (char)startCommunicationCommand + (char)startBasicAPI; + this->write(command); +} +void TrackPlatform_BasicConnector::sendStopCommand() +{ + std::string command = std::string() + (char)communicationControllerID + (char)stopCommunicationCommand; + this->write(command); +} TrackPlatform_BasicConnector::TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : rxLocation(rx), txLocation(tx), baudRate(baudRate) diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index c196387..3be5ae9 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -10,6 +10,9 @@ class TrackPlatform_BasicConnector std::string txLocation; uint32_t baudRate; + void sendStartCommand(); + void sendStopCommand(); + public: TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); virtual ~TrackPlatform_BasicConnector(); diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index 595ea83..4866e9b 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -8,6 +8,9 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne //TODO: write switch (mode) { + case USB: + res = new SerialConnector(rx, tx, baudRate); + break; case bluetooth: res = new SerialConnector(rx, tx, baudRate); break; From 04a05389b8eb12fc9f2eb0b776ec94862e878a1c Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 3 Aug 2017 22:25:42 +0300 Subject: [PATCH 023/336] =?UTF-8?q?*=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B0=20USB=20*=20=D0=A2=D0=B5=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D1=8C=20=D0=BD=D0=B5=D0=BB=D1=8C=D0=B7=D1=8F=20=D1=8F=D0=B2?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BF=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20=D0=B8=20?= =?UTF-8?q?=D1=87=D0=B8=D1=82=D0=B0=D1=82=D1=8C=20=D0=B8=D0=B7=20=D1=83?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=B0,=20?= =?UTF-8?q?=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BF=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=B0=D0=BC=20(=D0=BF=D0=B0?= =?UTF-8?q?=D0=BA=D0=B5=D1=82=D0=B0=D0=BC)=20*=20=D0=A3=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B0=D0=BA=D0=B5?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=D0=B8=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=8C=D1=8E=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BB=D0=BE=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=BD=D0=B0=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=20TrackPlatform=5FBasicConnector=20=D0=B8=20=D0=B5=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=BD=D0=B0=D1=81=D0=BB=D0=B5=D0=B4=D0=BD=D0=B8=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2=20(=D1=82.=D0=B5.=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=B0=D1=82=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BD=D0=B0=20=D1=83=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B8=D0=B5=D0=BC=D0=B0?= =?UTF-8?q?-=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0=D1=87=D0=B8).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/ConnectionModes.h | 3 +- code/c++/cxx-api/SerialConnector.cpp | 18 +++++------ code/c++/cxx-api/SerialConnector.h | 8 +++-- .../cxx-api/TrackPlatform_BasicConnector.cpp | 10 ++++++ .../cxx-api/TrackPlatform_BasicConnector.h | 14 +++++++-- .../cxx-api/TrackPlatform_BasicManagement.cpp | 26 +++++----------- .../cxx-api/TrackPlatform_BasicManagement.h | 3 -- code/c++/cxx-api/TrackPlatform_Manager.cpp | 5 ++- code/c++/cxx-api/cxx-api.vcxproj.filters | 31 ++++++++++++------- 9 files changed, 69 insertions(+), 49 deletions(-) diff --git a/code/c++/cxx-api/ConnectionModes.h b/code/c++/cxx-api/ConnectionModes.h index e6312d5..edfebb6 100644 --- a/code/c++/cxx-api/ConnectionModes.h +++ b/code/c++/cxx-api/ConnectionModes.h @@ -3,7 +3,8 @@ enum ConnectionModes { - bluetooth + USB, + bluetooth, }; #endif /* _CONNECTION_MODES_H_ */ diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index 8e0476b..b3bb509 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -1,5 +1,10 @@ #include "SerialConnector.h" +void SerialConnector::write(const std::string& s) +{ + writePort->write(s); +} + SerialConnector::SerialConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : TrackPlatform_BasicConnector(rx, tx, baudRate), readPort(new serial::Serial(rx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))), writePort((rx == tx) ? readPort : new serial::Serial(tx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))) @@ -20,17 +25,12 @@ std::string SerialConnector::read() return readPort->read(messageMaxSize); } -std::string SerialConnector::readAllAvailable() -{ - return (readPort->available() ? readPort->read(readPort->available()) : ""); -} - -void SerialConnector::write(const std::string& s) +bool SerialConnector::isConnected() { - writePort->write(s); + return (readPort->isOpen() && writePort->isOpen()); } -bool SerialConnector::isConnected() +std::string SerialConnector::readOneAnswer() { - return (readPort->isOpen() && writePort->isOpen()); + return readPort->readline(messageMaxSize, std::string(1, stopSymbol)); } diff --git a/code/c++/cxx-api/SerialConnector.h b/code/c++/cxx-api/SerialConnector.h index 6b448bd..f06d898 100644 --- a/code/c++/cxx-api/SerialConnector.h +++ b/code/c++/cxx-api/SerialConnector.h @@ -12,13 +12,15 @@ class SerialConnector : public TrackPlatform_BasicConnector serial::Serial* readPort; serial::Serial* writePort; +protected: + void write(const std::string& s) override; + std::string read() override; + public: SerialConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); ~SerialConnector() override; - std::string read() override; - std::string readAllAvailable() override; - void write(const std::string& s) override; bool isConnected() override; + std::string readOneAnswer() override; }; #endif /* _BLUETOOTH_CONNECTOR_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index df6c986..80d6a59 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -8,3 +8,13 @@ TrackPlatform_BasicConnector::TrackPlatform_BasicConnector(const std::string& rx TrackPlatform_BasicConnector::~TrackPlatform_BasicConnector() { } + +std::string TrackPlatform_BasicConnector::readOneAnswer() +{ + return read(); +} + +void TrackPlatform_BasicConnector::sendOneCommand(const std::string& s) +{ + write(s + stopSymbol); +} diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index c196387..de5eb10 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -10,13 +10,21 @@ class TrackPlatform_BasicConnector std::string txLocation; uint32_t baudRate; + static const char stopSymbol = '|'; + + virtual void write(const std::string& s) = 0; + virtual std::string read() = 0; + public: TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); virtual ~TrackPlatform_BasicConnector(); - virtual std::string read() = 0; - virtual std::string readAllAvailable() = 0; - virtual void write(const std::string& s) = 0; + /** + * @brief Read only one answer + * @warning By default returns one portion of data from rx, must be overriden if require + */ + virtual std::string readOneAnswer(); + virtual void sendOneCommand(const std::string& s); virtual bool isConnected() = 0; }; diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 28daf94..984cb69 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -2,27 +2,17 @@ void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) const { - sendOneCommand(static_cast(movementControllerID) + additionalInfo); + connector->sendOneCommand(static_cast(movementControllerID) + additionalInfo); } void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInfo) const { - sendOneCommand(static_cast(sensorsControllerID) + additionalInfo); + connector->sendOneCommand(static_cast(sensorsControllerID) + additionalInfo); } void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) const { - sendOneCommand(static_cast(servoControllerID) + additionalInfo); -} - -void TrackPlatform_BasicManagement::sendOneCommand(const std::string& info) const -{ - if (!connector) - { - throw std::exception("Bad memory"); - } - - connector->write(info + stopSymbol); + connector->sendOneCommand(static_cast(servoControllerID) + additionalInfo); } std::vector TrackPlatform_BasicManagement::parseStringToArray(std::string s) @@ -151,7 +141,7 @@ uint32_t TrackPlatform_BasicManagement::sensorDistanceGetValue(uint8_t num) cons std::string toSend(1, distance_sensor); toSend += std::to_string(num); sendSensors(toSend); - auto answer = connector->read(); + auto answer = connector->readOneAnswer(); return std::stoi(answer); } @@ -159,7 +149,7 @@ std::vector TrackPlatform_BasicManagement::sensorDistanceGetAllValues( { std::string toSend(1, distance_sensor_all); sendSensors(toSend); - return parseStringToArray(connector->read()); + return parseStringToArray(connector->readOneAnswer()); } uint32_t TrackPlatform_BasicManagement::sensorLineGetValue(uint8_t num) const @@ -167,7 +157,7 @@ uint32_t TrackPlatform_BasicManagement::sensorLineGetValue(uint8_t num) const std::string toSend(1, line_sensor); toSend += std::to_string(num); sendSensors(toSend); - auto answer = connector->read(); + auto answer = connector->readOneAnswer(); return std::stoi(answer); } @@ -175,7 +165,7 @@ std::vector TrackPlatform_BasicManagement::sensorLineGetAllValues() co { std::string toSend(1, line_sensor_all); sendSensors(toSend); - return parseStringToArray(connector->read()); + return parseStringToArray(connector->readOneAnswer()); } void TrackPlatform_BasicManagement::servoSetHorizontalAngle(uint16_t angle) const @@ -205,5 +195,5 @@ std::vector TrackPlatform_BasicManagement::servoGetAngles() const { std::string toSend(1, get_coodrinates); sendServo(toSend); - return parseStringToArray(connector->read()); + return parseStringToArray(connector->readOneAnswer()); } diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index a6fed73..b5258bb 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -13,15 +13,12 @@ class TrackPlatform_BasicManagement static const uint8_t minSpeed = 0; static const uint8_t maxSpeed = 255; static const char delimiter = ';'; - static const char stopSymbol = '|'; protected: void sendMove(const std::string& additionalInfo) const; void sendSensors(const std::string& additionalInfo) const; void sendServo(const std::string& additionalInfo) const; - void sendOneCommand(const std::string& info) const; - static std::vector parseStringToArray(std::string s); TrackPlatform_BasicConnector* getConnector() const; diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index 595ea83..e2f9706 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -5,9 +5,12 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne { TrackPlatform_BasicConnector* res; - //TODO: write + //TODO: add more modes switch (mode) { + case USB: + res = new SerialConnector(rx, tx, baudRate); + break; case bluetooth: res = new SerialConnector(rx, tx, baudRate); break; diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 19e9a30..422dcc7 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -22,6 +22,15 @@ {a897fa9d-d634-41b6-a441-71b4a660fa92} + + {09716c3b-089b-4880-b137-c4da5ccc81f8} + + + {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} + + + {8cb6d371-6c98-4f8c-ace2-6e3059467355} + @@ -30,9 +39,6 @@ Header Files - - Header Files - serial_support\header @@ -42,23 +48,23 @@ serial_support\header - - Header Files - Header Files - Header Files + Communication\header + + + Communication\header + + + Communication\header Source Files - - Source Files - serial_support\source @@ -72,7 +78,10 @@ Source Files - Source Files + Communication\source + + + Communication\source \ No newline at end of file From 7cd05735575796e1212cd864489d71d9d1d579a8 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 3 Aug 2017 22:41:44 +0300 Subject: [PATCH 024/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BF=D0=BE=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=80=D0=B5=D0=B6=D0=B8?= =?UTF-8?q?=D0=BC=D0=B0=D1=85,=20=D0=BE=D1=82=D0=BB=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20=D0=BE=D1=82=20Debug-x86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/cxx-app.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 7bc717f..654d30e 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -74,26 +74,26 @@ true $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(OutDir);$(LibraryPath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ true $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) - $(OutDir);$(LibraryPath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ false $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) - $(OutDir);$(LibraryPath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ false - $(OutDir);$(LibraryPath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ From 58a71a9c6ef9425f5b24e5a7822d458c405bce73 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 3 Aug 2017 22:58:56 +0300 Subject: [PATCH 025/336] =?UTF-8?q?=D0=9D=D0=B5=D1=81=D0=BA=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=BA=D0=BE=20=D0=BC=D0=B5=D0=BB=D0=BA=D0=B8=D1=85=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Убраны завичимости компиляции от платформы 10.0.14393.0 (теперь достаточно 8.1 версии) * Добавлены описания к функциям отправки стартовой и стоповой команд * Добавлена поддержка стартовых и стоповых команд для последовательных соединений. --- code/c++/cxx-api/SerialConnector.cpp | 3 +++ code/c++/cxx-api/TrackPlatform_BasicConnector.h | 8 ++++++++ code/c++/cxx-api/cxx-api.vcxproj | 1 - code/c++/cxx-app/cxx-app.vcxproj | 1 - 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index b3bb509..7e62ba0 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -9,10 +9,13 @@ SerialConnector::SerialConnector(const std::string& rx, const std::string& tx, u TrackPlatform_BasicConnector(rx, tx, baudRate), readPort(new serial::Serial(rx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))), writePort((rx == tx) ? readPort : new serial::Serial(tx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))) { + sendStartCommand(); } SerialConnector::~SerialConnector() { + sendStopCommand(); + if (readPort != writePort) { delete writePort; diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index 0b175bb..a71a9e9 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -15,7 +15,15 @@ class TrackPlatform_BasicConnector virtual void write(const std::string& s) = 0; virtual std::string read() = 0; + /** + * @brief Send start connection command + * @warning Must be called in constructor after configuring and opening connection + */ void sendStartCommand(); + /** + * @brief Send stop connection command + * @warning Must be called in destructor befor closing and deleting connection + */ void sendStopCommand(); public: diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 4b18457..d070776 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -23,7 +23,6 @@ {32D3778A-E59E-4DBC-8D86-BD23B708CA12} Win32Proj cxxapi - 10.0.14393.0 diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 654d30e..6c8eb23 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -23,7 +23,6 @@ {F92E7862-33C4-48B8-A055-3EE00352161F} Win32Proj cxxapp - 10.0.14393.0 From 82554f7bf4359b3fc9541a99391485b0088b72c9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 3 Aug 2017 23:00:47 +0300 Subject: [PATCH 026/336] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D0=BE=20?= =?UTF-8?q?=D1=82=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?Windows=2010=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF?= =?UTF-8?q?=D0=B8=D0=BB=D1=8F=D1=86=D0=B8=D0=B8=20(=D1=82=D0=B5=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D1=8C=20=D0=B4=D0=BE=D1=81=D1=82=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D0=BE=20=D0=BB=D1=8E=D0=B1=D0=BE=D0=B9=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=81=D0=B8=D0=B8=20Windows)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/cxx-api.vcxproj | 1 - code/c++/cxx-app/cxx-app.vcxproj | 1 - 2 files changed, 2 deletions(-) diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 4b18457..d070776 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -23,7 +23,6 @@ {32D3778A-E59E-4DBC-8D86-BD23B708CA12} Win32Proj cxxapi - 10.0.14393.0 diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 654d30e..6c8eb23 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -23,7 +23,6 @@ {F92E7862-33C4-48B8-A055-3EE00352161F} Win32Proj cxxapp - 10.0.14393.0 From d827350ddb5910a58e730653dd015be147d6e284 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 3 Aug 2017 23:26:12 +0300 Subject: [PATCH 027/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BA=D0=B0=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=D0=BE=D0=B2=20(=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4)=20=D0=B4=D0=BB=D1=8F=20=D0=BE?= =?UTF-8?q?=D1=82=D0=B2=D0=B5=D1=82=D0=B0=20=D0=BD=D0=B0=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/ConnectingDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Arduino/connectors/ConnectingDevice.cpp b/code/Arduino/connectors/ConnectingDevice.cpp index 573141b..4b94ea4 100644 --- a/code/Arduino/connectors/ConnectingDevice.cpp +++ b/code/Arduino/connectors/ConnectingDevice.cpp @@ -19,7 +19,7 @@ ConnectingDevice::ConnectingDevice(int rx, int tx, int speed) void ConnectingDevice::send(String data) { - device->print(data); + device->print(data + Constants::commands_stop_symbol); } bool ConnectingDevice::isActive() From 7c3eaba3b36f2fd627a1153e43ed545504b770dd Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 4 Aug 2017 09:33:03 +0300 Subject: [PATCH 028/336] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Теперь с устройством можно соединиться и потом переподключиться --- code/Arduino/trackPlatform.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index b8d40c4..7057d0d 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -26,13 +26,14 @@ ConnectingDevice *device = nullptr; CommandsController controller; DebugSerial debugSerial; -char connectCommand[] = { communicationControllerID, startCommunicationCommand, startBasicAPI }; -char disconnectCommand[] = {communicationControllerID, stopCommunicationCommand }; +char connectCommand[] = { communicationControllerID, startCommunicationCommand, startBasicAPI, 0}; +char disconnectCommand[] = {communicationControllerID, stopCommunicationCommand, 0}; bool connected = false; void selectDevice() { + connected = false; debugSerial.println("Arduino tries to found a manager"); while (!connected) { if (bluetooth.isActive() && bluetooth.read() == connectCommand) { From d2d154839fa8b23b3d83faee9cef36582e03c45e Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 7 Aug 2017 16:03:40 +0300 Subject: [PATCH 029/336] serial_support replacement with submodules --- .gitmodules | 3 + code/c++/cxx-api/serial_support | 1 + .../serial_support/include/serial/impl/unix.h | 221 ---- .../serial_support/include/serial/impl/win.h | 207 ---- .../serial_support/include/serial/serial.h | 775 ------------ .../serial_support/include/serial/v8stdint.h | 57 - .../src/impl/list_ports/list_ports_linux.cc | 335 ------ .../src/impl/list_ports/list_ports_osx.cc | 286 ----- .../src/impl/list_ports/list_ports_win.cc | 152 --- .../cxx-api/serial_support/src/impl/unix.cc | 1063 ----------------- .../cxx-api/serial_support/src/impl/win.cc | 640 ---------- code/c++/cxx-api/serial_support/src/serial.cc | 414 ------- 12 files changed, 4 insertions(+), 4150 deletions(-) create mode 100644 .gitmodules create mode 160000 code/c++/cxx-api/serial_support delete mode 100644 code/c++/cxx-api/serial_support/include/serial/impl/unix.h delete mode 100644 code/c++/cxx-api/serial_support/include/serial/impl/win.h delete mode 100644 code/c++/cxx-api/serial_support/include/serial/serial.h delete mode 100644 code/c++/cxx-api/serial_support/include/serial/v8stdint.h delete mode 100644 code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc delete mode 100644 code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc delete mode 100644 code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc delete mode 100644 code/c++/cxx-api/serial_support/src/impl/unix.cc delete mode 100644 code/c++/cxx-api/serial_support/src/impl/win.cc delete mode 100644 code/c++/cxx-api/serial_support/src/serial.cc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1486cf7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cxx_serial_support"] + path = code/c++/cxx-api/serial_support + url = git@github.com:wjwwood/serial.git diff --git a/code/c++/cxx-api/serial_support b/code/c++/cxx-api/serial_support new file mode 160000 index 0000000..827c4a7 --- /dev/null +++ b/code/c++/cxx-api/serial_support @@ -0,0 +1 @@ +Subproject commit 827c4a784dd4fdd35dc391f37ef152eab7c9c9b2 diff --git a/code/c++/cxx-api/serial_support/include/serial/impl/unix.h b/code/c++/cxx-api/serial_support/include/serial/impl/unix.h deleted file mode 100644 index 0fb38f2..0000000 --- a/code/c++/cxx-api/serial_support/include/serial/impl/unix.h +++ /dev/null @@ -1,221 +0,0 @@ -/*! - * \file serial/impl/unix.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a unix based pimpl for the Serial class. This implementation is - * based off termios.h and uses select for multiplexing the IO ports. - * - */ - -#if !defined(_WIN32) - -#ifndef SERIAL_IMPL_UNIX_H -#define SERIAL_IMPL_UNIX_H - -#include "serial/serial.h" - -#include - -namespace serial { - -using std::size_t; -using std::string; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class MillisecondTimer { -public: - MillisecondTimer(const uint32_t millis); - int64_t remaining(); - -private: - static timespec timespec_now(); - timespec expiry; -}; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - bool - waitReadable (uint32_t timeout); - - void - waitByteTimes (size_t count); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - string port_; // Path to the file descriptor - int fd_; // The current file descriptor - - bool is_open_; - bool xonxoff_; - bool rtscts_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - uint32_t byte_time_ns_; // Nanoseconds to transmit/receive a single byte - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - pthread_mutex_t read_mutex; - // Mutex used to lock the write functions - pthread_mutex_t write_mutex; -}; - -} - -#endif // SERIAL_IMPL_UNIX_H - -#endif // !defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/include/serial/impl/win.h b/code/c++/cxx-api/serial_support/include/serial/impl/win.h deleted file mode 100644 index 2c0c6cd..0000000 --- a/code/c++/cxx-api/serial_support/include/serial/impl/win.h +++ /dev/null @@ -1,207 +0,0 @@ -/*! - * \file serial/impl/windows.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a windows implementation of the Serial class interface. - * - */ - -#if defined(_WIN32) - -#ifndef SERIAL_IMPL_WINDOWS_H -#define SERIAL_IMPL_WINDOWS_H - -#include "serial/serial.h" - -#include "windows.h" - -namespace serial { - -using std::string; -using std::wstring; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - bool - waitReadable (uint32_t timeout); - - void - waitByteTimes (size_t count); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - wstring port_; // Path to the file descriptor - HANDLE fd_; - - bool is_open_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - HANDLE read_mutex; - // Mutex used to lock the write functions - HANDLE write_mutex; -}; - -} - -#endif // SERIAL_IMPL_WINDOWS_H - -#endif // if defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/include/serial/serial.h b/code/c++/cxx-api/serial_support/include/serial/serial.h deleted file mode 100644 index 1385659..0000000 --- a/code/c++/cxx-api/serial_support/include/serial/serial.h +++ /dev/null @@ -1,775 +0,0 @@ -/*! - * \file serial/serial.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a cross platform interface for interacting with Serial Ports. - */ - -#ifndef SERIAL_H -#define SERIAL_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ -__LINE__, (message) ) - -namespace serial { - -/*! - * Enumeration defines the possible bytesizes for the serial port. - */ -typedef enum { - fivebits = 5, - sixbits = 6, - sevenbits = 7, - eightbits = 8 -} bytesize_t; - -/*! - * Enumeration defines the possible parity types for the serial port. - */ -typedef enum { - parity_none = 0, - parity_odd = 1, - parity_even = 2, - parity_mark = 3, - parity_space = 4 -} parity_t; - -/*! - * Enumeration defines the possible stopbit types for the serial port. - */ -typedef enum { - stopbits_one = 1, - stopbits_two = 2, - stopbits_one_point_five -} stopbits_t; - -/*! - * Enumeration defines the possible flowcontrol types for the serial port. - */ -typedef enum { - flowcontrol_none = 0, - flowcontrol_software, - flowcontrol_hardware -} flowcontrol_t; - -/*! - * Structure for setting the timeout of the serial port, times are - * in milliseconds. - * - * In order to disable the interbyte timeout, set it to Timeout::max(). - */ -struct Timeout { -#ifdef max -# undef max -#endif - static uint32_t max() {return std::numeric_limits::max();} - /*! - * Convenience function to generate Timeout structs using a - * single absolute timeout. - * - * \param timeout A long that defines the time in milliseconds until a - * timeout occurs after a call to read or write is made. - * - * \return Timeout struct that represents this simple timeout provided. - */ - static Timeout simpleTimeout(uint32_t timeout) { - return Timeout(max(), timeout, 0, timeout, 0); - } - - /*! Number of milliseconds between bytes received to timeout on. */ - uint32_t inter_byte_timeout; - /*! A constant number of milliseconds to wait after calling read. */ - uint32_t read_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling read. - */ - uint32_t read_timeout_multiplier; - /*! A constant number of milliseconds to wait after calling write. */ - uint32_t write_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling write. - */ - uint32_t write_timeout_multiplier; - - explicit Timeout (uint32_t inter_byte_timeout_=0, - uint32_t read_timeout_constant_=0, - uint32_t read_timeout_multiplier_=0, - uint32_t write_timeout_constant_=0, - uint32_t write_timeout_multiplier_=0) - : inter_byte_timeout(inter_byte_timeout_), - read_timeout_constant(read_timeout_constant_), - read_timeout_multiplier(read_timeout_multiplier_), - write_timeout_constant(write_timeout_constant_), - write_timeout_multiplier(write_timeout_multiplier_) - {} -}; - -/*! - * Class that provides a portable serial port interface. - */ -class Serial { -public: - /*! - * Creates a Serial object and opens the port if a port is specified, - * otherwise it remains closed until serial::Serial::open is called. - * - * \param port A std::string containing the address of the serial port, - * which would be something like 'COM1' on Windows and '/dev/ttyS0' - * on Linux. - * - * \param baudrate An unsigned 32-bit integer that represents the baudrate - * - * \param timeout A serial::Timeout struct that defines the timeout - * conditions for the serial port. \see serial::Timeout - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \param flowcontrol Type of flowcontrol used, default is - * flowcontrol_none, possible values are: flowcontrol_none, - * flowcontrol_software, flowcontrol_hardware - * - * \throw serial::PortNotOpenedException - * \throw serial::IOException - * \throw std::invalid_argument - */ - Serial (const std::string &port = "", - uint32_t baudrate = 9600, - Timeout timeout = Timeout(), - bytesize_t bytesize = eightbits, - parity_t parity = parity_none, - stopbits_t stopbits = stopbits_one, - flowcontrol_t flowcontrol = flowcontrol_none); - - /*! Destructor */ - virtual ~Serial (); - - /*! - * Opens the serial port as long as the port is set and the port isn't - * already open. - * - * If the port is provided to the constructor then an explicit call to open - * is not needed. - * - * \see Serial::Serial - * - * \throw std::invalid_argument - * \throw serial::SerialException - * \throw serial::IOException - */ - void - open (); - - /*! Gets the open status of the serial port. - * - * \return Returns true if the port is open, false otherwise. - */ - bool - isOpen () const; - - /*! Closes the serial port. */ - void - close (); - - /*! Return the number of characters in the buffer. */ - size_t - available (); - - /*! Block until there is serial data to read or read_timeout_constant - * number of milliseconds have elapsed. The return value is true when - * the function exits with the port in a readable state, false otherwise - * (due to timeout or select interruption). */ - bool - waitReadable (); - - /*! Block for a period of time corresponding to the transmission time of - * count characters at present serial settings. This may be used in con- - * junction with waitReadable to read larger blocks of data from the - * port. */ - void - waitByteTimes (size_t count); - - /*! Read a given amount of bytes from the serial port into a given buffer. - * - * The read function will return in one of three cases: - * * The number of requested bytes was read. - * * In this case the number of bytes requested will match the size_t - * returned by read. - * * A timeout occurred, in this case the number of bytes read will not - * match the amount requested, but no exception will be thrown. One of - * two possible timeouts occurred: - * * The inter byte timeout expired, this means that number of - * milliseconds elapsed between receiving bytes from the serial port - * exceeded the inter byte timeout. - * * The total timeout expired, which is calculated by multiplying the - * read timeout multiplier by the number of requested bytes and then - * added to the read timeout constant. If that total number of - * milliseconds elapses after the initial call to read a timeout will - * occur. - * * An exception occurred, in this case an actual exception will be thrown. - * - * \param buffer An uint8_t array of at least the requested size. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - read (uint8_t *buffer, size_t size); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::vector of uint8_t. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - read (std::vector &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::string. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - read (std::string &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port and return a string - * containing the data. - * - * \param size A size_t defining how many bytes to be read. - * - * \return A std::string containing the data read from the port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - std::string - read (size_t size = 1); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param buffer A std::string reference used to store the data. - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A size_t representing the number of bytes read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A std::string containing the line. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - std::string - readline (size_t size = 65536, std::string eol = "\n"); - - /*! Reads in multiple lines until the serial port times out. - * - * This requires a timeout > 0 before it can be run. It will read until a - * timeout occurs and return a list of strings. - * - * \param size A maximum length of combined lines, defaults to 65536 (2^16) - * - * \param eol A string to match against for the EOL. - * - * \return A vector containing the lines. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - std::vector - readlines (size_t size = 65536, std::string eol = "\n"); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \param size A size_t that indicates how many bytes should be written from - * the given data buffer. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - * \throw serial::IOException - */ - size_t - write (const uint8_t *data, size_t size); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - * \throw serial::IOException - */ - size_t - write (const std::vector &data); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - * \throw serial::IOException - */ - size_t - write (const std::string &data); - - /*! Sets the serial port identifier. - * - * \param port A const std::string reference containing the address of the - * serial port, which would be something like 'COM1' on Windows and - * '/dev/ttyS0' on Linux. - * - * \throw std::invalid_argument - */ - void - setPort (const std::string &port); - - /*! Gets the serial port identifier. - * - * \see Serial::setPort - * - * \throw std::invalid_argument - */ - std::string - getPort () const; - - /*! Sets the timeout for reads and writes using the Timeout struct. - * - * There are two timeout conditions described here: - * * The inter byte timeout: - * * The inter_byte_timeout component of serial::Timeout defines the - * maximum amount of time, in milliseconds, between receiving bytes on - * the serial port that can pass before a timeout occurs. Setting this - * to zero will prevent inter byte timeouts from occurring. - * * Total time timeout: - * * The constant and multiplier component of this timeout condition, - * for both read and write, are defined in serial::Timeout. This - * timeout occurs if the total time since the read or write call was - * made exceeds the specified time in milliseconds. - * * The limit is defined by multiplying the multiplier component by the - * number of requested bytes and adding that product to the constant - * component. In this way if you want a read call, for example, to - * timeout after exactly one second regardless of the number of bytes - * you asked for then set the read_timeout_constant component of - * serial::Timeout to 1000 and the read_timeout_multiplier to zero. - * This timeout condition can be used in conjunction with the inter - * byte timeout condition with out any problems, timeout will simply - * occur when one of the two timeout conditions is met. This allows - * users to have maximum control over the trade-off between - * responsiveness and efficiency. - * - * Read and write functions will return in one of three cases. When the - * reading or writing is complete, when a timeout occurs, or when an - * exception occurs. - * - * A timeout of 0 enables non-blocking mode. - * - * \param timeout A serial::Timeout struct containing the inter byte - * timeout, and the read and write timeout constants and multipliers. - * - * \see serial::Timeout - */ - void - setTimeout (Timeout &timeout); - - /*! Sets the timeout for reads and writes. */ - void - setTimeout (uint32_t inter_byte_timeout, uint32_t read_timeout_constant, - uint32_t read_timeout_multiplier, uint32_t write_timeout_constant, - uint32_t write_timeout_multiplier) - { - Timeout timeout(inter_byte_timeout, read_timeout_constant, - read_timeout_multiplier, write_timeout_constant, - write_timeout_multiplier); - return setTimeout(timeout); - } - - /*! Gets the timeout for reads in seconds. - * - * \return A Timeout struct containing the inter_byte_timeout, and read - * and write timeout constants and multipliers. - * - * \see Serial::setTimeout - */ - Timeout - getTimeout () const; - - /*! Sets the baudrate for the serial port. - * - * Possible baudrates depends on the system but some safe baudrates include: - * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, - * 57600, 115200 - * Some other baudrates that are supported by some comports: - * 128000, 153600, 230400, 256000, 460800, 921600 - * - * \param baudrate An integer that sets the baud rate for the serial port. - * - * \throw std::invalid_argument - */ - void - setBaudrate (uint32_t baudrate); - - /*! Gets the baudrate for the serial port. - * - * \return An integer that sets the baud rate for the serial port. - * - * \see Serial::setBaudrate - * - * \throw std::invalid_argument - */ - uint32_t - getBaudrate () const; - - /*! Sets the bytesize for the serial port. - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \throw std::invalid_argument - */ - void - setBytesize (bytesize_t bytesize); - - /*! Gets the bytesize for the serial port. - * - * \see Serial::setBytesize - * - * \throw std::invalid_argument - */ - bytesize_t - getBytesize () const; - - /*! Sets the parity for the serial port. - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \throw std::invalid_argument - */ - void - setParity (parity_t parity); - - /*! Gets the parity for the serial port. - * - * \see Serial::setParity - * - * \throw std::invalid_argument - */ - parity_t - getParity () const; - - /*! Sets the stopbits for the serial port. - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \throw std::invalid_argument - */ - void - setStopbits (stopbits_t stopbits); - - /*! Gets the stopbits for the serial port. - * - * \see Serial::setStopbits - * - * \throw std::invalid_argument - */ - stopbits_t - getStopbits () const; - - /*! Sets the flow control for the serial port. - * - * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, - * possible values are: flowcontrol_none, flowcontrol_software, - * flowcontrol_hardware - * - * \throw std::invalid_argument - */ - void - setFlowcontrol (flowcontrol_t flowcontrol); - - /*! Gets the flow control for the serial port. - * - * \see Serial::setFlowcontrol - * - * \throw std::invalid_argument - */ - flowcontrol_t - getFlowcontrol () const; - - /*! Flush the input and output buffers */ - void - flush (); - - /*! Flush only the input buffer */ - void - flushInput (); - - /*! Flush only the output buffer */ - void - flushOutput (); - - /*! Sends the RS-232 break signal. See tcsendbreak(3). */ - void - sendBreak (int duration); - - /*! Set the break condition to a given level. Defaults to true. */ - void - setBreak (bool level = true); - - /*! Set the RTS handshaking line to the given level. Defaults to true. */ - void - setRTS (bool level = true); - - /*! Set the DTR handshaking line to the given level. Defaults to true. */ - void - setDTR (bool level = true); - - /*! - * Blocks until CTS, DSR, RI, CD changes or something interrupts it. - * - * Can throw an exception if an error occurs while waiting. - * You can check the status of CTS, DSR, RI, and CD once this returns. - * Uses TIOCMIWAIT via ioctl if available (mostly only on Linux) with a - * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a - * polling method is used which can give +-2ms. - * - * \return Returns true if one of the lines changed, false if something else - * occurred. - * - * \throw SerialException - */ - bool - waitForChange (); - - /*! Returns the current status of the CTS line. */ - bool - getCTS (); - - /*! Returns the current status of the DSR line. */ - bool - getDSR (); - - /*! Returns the current status of the RI line. */ - bool - getRI (); - - /*! Returns the current status of the CD line. */ - bool - getCD (); - -private: - // Disable copy constructors - Serial(const Serial&); - Serial& operator=(const Serial&); - - // Pimpl idiom, d_pointer - class SerialImpl; - SerialImpl *pimpl_; - - // Scoped Lock Classes - class ScopedReadLock; - class ScopedWriteLock; - - // Read common function - size_t - read_ (uint8_t *buffer, size_t size); - // Write common function - size_t - write_ (const uint8_t *data, size_t length); - -}; - -class SerialException : public std::exception -{ - // Disable copy constructors - SerialException& operator=(const SerialException&); - std::string e_what_; -public: - SerialException (const char *description) { - std::stringstream ss; - ss << "SerialException " << description << " failed."; - e_what_ = ss.str(); - } - SerialException (const SerialException& other) : e_what_(other.e_what_) {} - virtual ~SerialException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class IOException : public std::exception -{ - // Disable copy constructors - IOException& operator=(const IOException&); - std::string file_; - int line_; - std::string e_what_; - int errno_; -public: - explicit IOException (std::string file, int line, int errnum) - : file_(file), line_(line), errno_(errnum) { - std::stringstream ss; -#if defined(_WIN32) && !defined(__MINGW32__) - char error_str [1024]; - strerror_s(error_str, 1024, errnum); -#else - char * error_str = strerror(errnum); -#endif - ss << "IO Exception (" << errno_ << "): " << error_str; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - explicit IOException (std::string file, int line, const char * description) - : file_(file), line_(line), errno_(0) { - std::stringstream ss; - ss << "IO Exception: " << description; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - virtual ~IOException() throw() {} - IOException (const IOException& other) : line_(other.line_), e_what_(other.e_what_), errno_(other.errno_) {} - - int getErrorNumber () const { return errno_; } - - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class PortNotOpenedException : public std::exception -{ - // Disable copy constructors - const PortNotOpenedException& operator=(PortNotOpenedException); - std::string e_what_; -public: - PortNotOpenedException (const char * description) { - std::stringstream ss; - ss << "PortNotOpenedException " << description << " failed."; - e_what_ = ss.str(); - } - PortNotOpenedException (const PortNotOpenedException& other) : e_what_(other.e_what_) {} - virtual ~PortNotOpenedException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -/*! - * Structure that describes a serial device. - */ -struct PortInfo { - - /*! Address of the serial port (this can be passed to the constructor of Serial). */ - std::string port; - - /*! Human readable description of serial device if available. */ - std::string description; - - /*! Hardware ID (e.g. VID:PID of USB serial devices) or "n/a" if not available. */ - std::string hardware_id; - -}; - -/* Lists the serial ports available on the system - * - * Returns a vector of available serial ports, each represented - * by a serial::PortInfo data structure: - * - * \return vector of serial::PortInfo. - */ -std::vector -list_ports(); - -} // namespace serial - -#endif diff --git a/code/c++/cxx-api/serial_support/include/serial/v8stdint.h b/code/c++/cxx-api/serial_support/include/serial/v8stdint.h deleted file mode 100644 index f3be96b..0000000 --- a/code/c++/cxx-api/serial_support/include/serial/v8stdint.h +++ /dev/null @@ -1,57 +0,0 @@ -// This header is from the v8 google project: -// http://code.google.com/p/v8/source/browse/trunk/include/v8stdint.h - -// Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Load definitions of standard types. - -#ifndef V8STDINT_H_ -#define V8STDINT_H_ - -#include -#include - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include - -#endif - -#endif // V8STDINT_H_ diff --git a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc deleted file mode 100644 index 9779d5e..0000000 --- a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_linux.cc +++ /dev/null @@ -1,335 +0,0 @@ -#if defined(__linux__) - -/* - * Copyright (c) 2014 Craig Lilley - * This software is made available under the terms of the MIT licence. - * A copy of the licence can be obtained from: - * http://opensource.org/licenses/MIT - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "serial/serial.h" - -using serial::PortInfo; -using std::istringstream; -using std::ifstream; -using std::getline; -using std::vector; -using std::string; -using std::cout; -using std::endl; - -static vector glob(const vector& patterns); -static string basename(const string& path); -static string dirname(const string& path); -static bool path_exists(const string& path); -static string realpath(const string& path); -static string usb_sysfs_friendly_name(const string& sys_usb_path); -static vector get_sysfs_info(const string& device_path); -static string read_line(const string& file); -static string usb_sysfs_hw_string(const string& sysfs_path); -static string format(const char* format, ...); - -vector -glob(const vector& patterns) -{ - vector paths_found; - - if(patterns.size() == 0) - return paths_found; - - glob_t glob_results; - - int glob_retval = glob(patterns[0].c_str(), 0, NULL, &glob_results); - - vector::const_iterator iter = patterns.begin(); - - while(++iter != patterns.end()) - { - glob_retval = glob(iter->c_str(), GLOB_APPEND, NULL, &glob_results); - } - - for(int path_index = 0; path_index < glob_results.gl_pathc; path_index++) - { - paths_found.push_back(glob_results.gl_pathv[path_index]); - } - - globfree(&glob_results); - - return paths_found; -} - -string -basename(const string& path) -{ - size_t pos = path.rfind("/"); - - if(pos == std::string::npos) - return path; - - return string(path, pos+1, string::npos); -} - -string -dirname(const string& path) -{ - size_t pos = path.rfind("/"); - - if(pos == std::string::npos) - return path; - else if(pos == 0) - return "/"; - - return string(path, 0, pos); -} - -bool -path_exists(const string& path) -{ - struct stat sb; - - if( stat(path.c_str(), &sb ) == 0 ) - return true; - - return false; -} - -string -realpath(const string& path) -{ - char* real_path = realpath(path.c_str(), NULL); - - string result; - - if(real_path != NULL) - { - result = real_path; - - free(real_path); - } - - return result; -} - -string -usb_sysfs_friendly_name(const string& sys_usb_path) -{ - unsigned int device_number = 0; - - istringstream( read_line(sys_usb_path + "/devnum") ) >> device_number; - - string manufacturer = read_line( sys_usb_path + "/manufacturer" ); - - string product = read_line( sys_usb_path + "/product" ); - - string serial = read_line( sys_usb_path + "/serial" ); - - if( manufacturer.empty() && product.empty() && serial.empty() ) - return ""; - - return format("%s %s %s", manufacturer.c_str(), product.c_str(), serial.c_str() ); -} - -vector -get_sysfs_info(const string& device_path) -{ - string device_name = basename( device_path ); - - string friendly_name; - - string hardware_id; - - string sys_device_path = format( "/sys/class/tty/%s/device", device_name.c_str() ); - - if( device_name.compare(0,6,"ttyUSB") == 0 ) - { - sys_device_path = dirname( dirname( realpath( sys_device_path ) ) ); - - if( path_exists( sys_device_path ) ) - { - friendly_name = usb_sysfs_friendly_name( sys_device_path ); - - hardware_id = usb_sysfs_hw_string( sys_device_path ); - } - } - else if( device_name.compare(0,6,"ttyACM") == 0 ) - { - sys_device_path = dirname( realpath( sys_device_path ) ); - - if( path_exists( sys_device_path ) ) - { - friendly_name = usb_sysfs_friendly_name( sys_device_path ); - - hardware_id = usb_sysfs_hw_string( sys_device_path ); - } - } - else - { - // Try to read ID string of PCI device - - string sys_id_path = sys_device_path + "/id"; - - if( path_exists( sys_id_path ) ) - hardware_id = read_line( sys_id_path ); - } - - if( friendly_name.empty() ) - friendly_name = device_name; - - if( hardware_id.empty() ) - hardware_id = "n/a"; - - vector result; - result.push_back(friendly_name); - result.push_back(hardware_id); - - return result; -} - -string -read_line(const string& file) -{ - ifstream ifs(file.c_str(), ifstream::in); - - string line; - - if(ifs) - { - getline(ifs, line); - } - - return line; -} - -string -format(const char* format, ...) -{ - va_list ap; - - size_t buffer_size_bytes = 256; - - string result; - - char* buffer = (char*)malloc(buffer_size_bytes); - - if( buffer == NULL ) - return result; - - bool done = false; - - unsigned int loop_count = 0; - - while(!done) - { - va_start(ap, format); - - int return_value = vsnprintf(buffer, buffer_size_bytes, format, ap); - - if( return_value < 0 ) - { - done = true; - } - else if( return_value >= buffer_size_bytes ) - { - // Realloc and try again. - - buffer_size_bytes = return_value + 1; - - char* new_buffer_ptr = (char*)realloc(buffer, buffer_size_bytes); - - if( new_buffer_ptr == NULL ) - { - done = true; - } - else - { - buffer = new_buffer_ptr; - } - } - else - { - result = buffer; - done = true; - } - - va_end(ap); - - if( ++loop_count > 5 ) - done = true; - } - - free(buffer); - - return result; -} - -string -usb_sysfs_hw_string(const string& sysfs_path) -{ - string serial_number = read_line( sysfs_path + "/serial" ); - - if( serial_number.length() > 0 ) - { - serial_number = format( "SNR=%s", serial_number.c_str() ); - } - - string vid = read_line( sysfs_path + "/idVendor" ); - - string pid = read_line( sysfs_path + "/idProduct" ); - - return format("USB VID:PID=%s:%s %s", vid.c_str(), pid.c_str(), serial_number.c_str() ); -} - -vector -serial::list_ports() -{ - vector results; - - vector search_globs; - search_globs.push_back("/dev/ttyACM*"); - search_globs.push_back("/dev/ttyS*"); - search_globs.push_back("/dev/ttyUSB*"); - search_globs.push_back("/dev/tty.*"); - search_globs.push_back("/dev/cu.*"); - - vector devices_found = glob( search_globs ); - - vector::iterator iter = devices_found.begin(); - - while( iter != devices_found.end() ) - { - string device = *iter++; - - vector sysfs_info = get_sysfs_info( device ); - - string friendly_name = sysfs_info[0]; - - string hardware_id = sysfs_info[1]; - - PortInfo device_entry; - device_entry.port = device; - device_entry.description = friendly_name; - device_entry.hardware_id = hardware_id; - - results.push_back( device_entry ); - - } - - return results; -} - -#endif // defined(__linux__) diff --git a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc deleted file mode 100644 index 333c55c..0000000 --- a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_osx.cc +++ /dev/null @@ -1,286 +0,0 @@ -#if defined(__APPLE__) - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "serial/serial.h" - -using serial::PortInfo; -using std::string; -using std::vector; - -#define HARDWARE_ID_STRING_LENGTH 128 - -string cfstring_to_string( CFStringRef cfstring ); -string get_device_path( io_object_t& serial_port ); -string get_class_name( io_object_t& obj ); -io_registry_entry_t get_parent_iousb_device( io_object_t& serial_port ); -string get_string_property( io_object_t& device, const char* property ); -uint16_t get_int_property( io_object_t& device, const char* property ); -string rtrim(const string& str); - -string -cfstring_to_string( CFStringRef cfstring ) -{ - char cstring[MAXPATHLEN]; - string result; - - if( cfstring ) - { - Boolean success = CFStringGetCString( cfstring, - cstring, - sizeof(cstring), - kCFStringEncodingASCII ); - - if( success ) - result = cstring; - } - - return result; -} - -string -get_device_path( io_object_t& serial_port ) -{ - CFTypeRef callout_path; - string device_path; - - callout_path = IORegistryEntryCreateCFProperty( serial_port, - CFSTR(kIOCalloutDeviceKey), - kCFAllocatorDefault, - 0 ); - - if (callout_path) - { - if( CFGetTypeID(callout_path) == CFStringGetTypeID() ) - device_path = cfstring_to_string( static_cast(callout_path) ); - - CFRelease(callout_path); - } - - return device_path; -} - -string -get_class_name( io_object_t& obj ) -{ - string result; - io_name_t class_name; - kern_return_t kern_result; - - kern_result = IOObjectGetClass( obj, class_name ); - - if( kern_result == KERN_SUCCESS ) - result = class_name; - - return result; -} - -io_registry_entry_t -get_parent_iousb_device( io_object_t& serial_port ) -{ - io_object_t device = serial_port; - io_registry_entry_t parent = 0; - io_registry_entry_t result = 0; - kern_return_t kern_result = KERN_FAILURE; - string name = get_class_name(device); - - // Walk the IO Registry tree looking for this devices parent IOUSBDevice. - while( name != "IOUSBDevice" ) - { - kern_result = IORegistryEntryGetParentEntry( device, - kIOServicePlane, - &parent ); - - if(kern_result != KERN_SUCCESS) - { - result = 0; - break; - } - - device = parent; - - name = get_class_name(device); - } - - if(kern_result == KERN_SUCCESS) - result = device; - - return result; -} - -string -get_string_property( io_object_t& device, const char* property ) -{ - string property_name; - - if( device ) - { - CFStringRef property_as_cfstring = CFStringCreateWithCString ( - kCFAllocatorDefault, - property, - kCFStringEncodingASCII ); - - CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty( - device, - property_as_cfstring, - kCFAllocatorDefault, - 0 ); - - if( name_as_cfstring ) - { - if( CFGetTypeID(name_as_cfstring) == CFStringGetTypeID() ) - property_name = cfstring_to_string( static_cast(name_as_cfstring) ); - - CFRelease(name_as_cfstring); - } - - if(property_as_cfstring) - CFRelease(property_as_cfstring); - } - - return property_name; -} - -uint16_t -get_int_property( io_object_t& device, const char* property ) -{ - uint16_t result = 0; - - if( device ) - { - CFStringRef property_as_cfstring = CFStringCreateWithCString ( - kCFAllocatorDefault, - property, - kCFStringEncodingASCII ); - - CFTypeRef number = IORegistryEntryCreateCFProperty( device, - property_as_cfstring, - kCFAllocatorDefault, - 0 ); - - if(property_as_cfstring) - CFRelease(property_as_cfstring); - - if( number ) - { - if( CFGetTypeID(number) == CFNumberGetTypeID() ) - { - bool success = CFNumberGetValue( static_cast(number), - kCFNumberSInt16Type, - &result ); - - if( !success ) - result = 0; - } - - CFRelease(number); - } - - } - - return result; -} - -string rtrim(const string& str) -{ - string result = str; - - string whitespace = " \t\f\v\n\r"; - - std::size_t found = result.find_last_not_of(whitespace); - - if (found != std::string::npos) - result.erase(found+1); - else - result.clear(); - - return result; -} - -vector -serial::list_ports(void) -{ - vector devices_found; - CFMutableDictionaryRef classes_to_match; - io_iterator_t serial_port_iterator; - io_object_t serial_port; - mach_port_t master_port; - kern_return_t kern_result; - - kern_result = IOMasterPort(MACH_PORT_NULL, &master_port); - - if(kern_result != KERN_SUCCESS) - return devices_found; - - classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue); - - if (classes_to_match == NULL) - return devices_found; - - CFDictionarySetValue( classes_to_match, - CFSTR(kIOSerialBSDTypeKey), - CFSTR(kIOSerialBSDAllTypes) ); - - kern_result = IOServiceGetMatchingServices(master_port, classes_to_match, &serial_port_iterator); - - if (KERN_SUCCESS != kern_result) - return devices_found; - - while ( (serial_port = IOIteratorNext(serial_port_iterator)) ) - { - string device_path = get_device_path( serial_port ); - io_registry_entry_t parent = get_parent_iousb_device( serial_port ); - IOObjectRelease(serial_port); - - if( device_path.empty() ) - continue; - - PortInfo port_info; - port_info.port = device_path; - port_info.description = "n/a"; - port_info.hardware_id = "n/a"; - - string device_name = rtrim( get_string_property( parent, "USB Product Name" ) ); - string vendor_name = rtrim( get_string_property( parent, "USB Vendor Name") ); - string description = rtrim( vendor_name + " " + device_name ); - if( !description.empty() ) - port_info.description = description; - - string serial_number = rtrim(get_string_property( parent, "USB Serial Number" ) ); - uint16_t vendor_id = get_int_property( parent, "idVendor" ); - uint16_t product_id = get_int_property( parent, "idProduct" ); - - if( vendor_id && product_id ) - { - char cstring[HARDWARE_ID_STRING_LENGTH]; - - if(serial_number.empty()) - serial_number = "None"; - - int ret = snprintf( cstring, HARDWARE_ID_STRING_LENGTH, "USB VID:PID=%04x:%04x SNR=%s", - vendor_id, - product_id, - serial_number.c_str() ); - - if( (ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH) ) - port_info.hardware_id = cstring; - } - - devices_found.push_back(port_info); - } - - IOObjectRelease(serial_port_iterator); - return devices_found; -} - -#endif // defined(__APPLE__) diff --git a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc b/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc deleted file mode 100644 index 7da40c4..0000000 --- a/code/c++/cxx-api/serial_support/src/impl/list_ports/list_ports_win.cc +++ /dev/null @@ -1,152 +0,0 @@ -#if defined(_WIN32) - -/* - * Copyright (c) 2014 Craig Lilley - * This software is made available under the terms of the MIT licence. - * A copy of the licence can be obtained from: - * http://opensource.org/licenses/MIT - */ - -#include "serial/serial.h" -#include -#include -#include -#include -#include -#include - -using serial::PortInfo; -using std::vector; -using std::string; - -static const DWORD port_name_max_length = 256; -static const DWORD friendly_name_max_length = 256; -static const DWORD hardware_id_max_length = 256; - -// Convert a wide Unicode string to an UTF8 string -std::string utf8_encode(const std::wstring &wstr) -{ - int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); - std::string strTo( size_needed, 0 ); - WideCharToMultiByte (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); - return strTo; -} - -vector -serial::list_ports() -{ - vector devices_found; - - HDEVINFO device_info_set = SetupDiGetClassDevs( - (const GUID *) &GUID_DEVCLASS_PORTS, - NULL, - NULL, - DIGCF_PRESENT); - - unsigned int device_info_set_index = 0; - SP_DEVINFO_DATA device_info_data; - - device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); - - while(SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data)) - { - device_info_set_index++; - - // Get port name - - HKEY hkey = SetupDiOpenDevRegKey( - device_info_set, - &device_info_data, - DICS_FLAG_GLOBAL, - 0, - DIREG_DEV, - KEY_READ); - - TCHAR port_name[port_name_max_length]; - DWORD port_name_length = port_name_max_length; - - LONG return_code = RegQueryValueEx( - hkey, - _T("PortName"), - NULL, - NULL, - (LPBYTE)port_name, - &port_name_length); - - RegCloseKey(hkey); - - if(return_code != EXIT_SUCCESS) - continue; - - if(port_name_length > 0 && port_name_length <= port_name_max_length) - port_name[port_name_length-1] = '\0'; - else - port_name[0] = '\0'; - - // Ignore parallel ports - - if(_tcsstr(port_name, _T("LPT")) != NULL) - continue; - - // Get port friendly name - - TCHAR friendly_name[friendly_name_max_length]; - DWORD friendly_name_actual_length = 0; - - BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty( - device_info_set, - &device_info_data, - SPDRP_FRIENDLYNAME, - NULL, - (PBYTE)friendly_name, - friendly_name_max_length, - &friendly_name_actual_length); - - if(got_friendly_name == TRUE && friendly_name_actual_length > 0) - friendly_name[friendly_name_actual_length-1] = '\0'; - else - friendly_name[0] = '\0'; - - // Get hardware ID - - TCHAR hardware_id[hardware_id_max_length]; - DWORD hardware_id_actual_length = 0; - - BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty( - device_info_set, - &device_info_data, - SPDRP_HARDWAREID, - NULL, - (PBYTE)hardware_id, - hardware_id_max_length, - &hardware_id_actual_length); - - if(got_hardware_id == TRUE && hardware_id_actual_length > 0) - hardware_id[hardware_id_actual_length-1] = '\0'; - else - hardware_id[0] = '\0'; - - #ifdef UNICODE - std::string portName = utf8_encode(port_name); - std::string friendlyName = utf8_encode(friendly_name); - std::string hardwareId = utf8_encode(hardware_id); - #else - std::string portName = port_name; - std::string friendlyName = friendly_name; - std::string hardwareId = hardware_id; - #endif - - PortInfo port_entry; - port_entry.port = portName; - port_entry.description = friendlyName; - port_entry.hardware_id = hardwareId; - - devices_found.push_back(port_entry); - } - - SetupDiDestroyDeviceInfoList(device_info_set); - - return devices_found; -} - -#endif // #if defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/src/impl/unix.cc b/code/c++/cxx-api/serial_support/src/impl/unix.cc deleted file mode 100644 index 4ef6b32..0000000 --- a/code/c++/cxx-api/serial_support/src/impl/unix.cc +++ /dev/null @@ -1,1063 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison - * - * Additional Contributors: Christopher Baker @bakercp - */ - -#if !defined(_WIN32) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__linux__) -# include -#endif - -#include -#include -#include -#ifdef __MACH__ -#include -#include -#include -#endif - -#include "serial/impl/unix.h" - -#ifndef TIOCINQ -#ifdef FIONREAD -#define TIOCINQ FIONREAD -#else -#define TIOCINQ 0x541B -#endif -#endif - -#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3) -#include -#endif - -using std::string; -using std::stringstream; -using std::invalid_argument; -using serial::MillisecondTimer; -using serial::Serial; -using serial::SerialException; -using serial::PortNotOpenedException; -using serial::IOException; - - -MillisecondTimer::MillisecondTimer (const uint32_t millis) - : expiry(timespec_now()) -{ - int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6); - if (tv_nsec >= 1e9) { - int64_t sec_diff = tv_nsec / static_cast (1e9); - expiry.tv_nsec = tv_nsec % static_cast(1e9); - expiry.tv_sec += sec_diff; - } else { - expiry.tv_nsec = tv_nsec; - } -} - -int64_t -MillisecondTimer::remaining () -{ - timespec now(timespec_now()); - int64_t millis = (expiry.tv_sec - now.tv_sec) * 1e3; - millis += (expiry.tv_nsec - now.tv_nsec) / 1e6; - return millis; -} - -timespec -MillisecondTimer::timespec_now () -{ - timespec time; -# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - time.tv_sec = mts.tv_sec; - time.tv_nsec = mts.tv_nsec; -# else - clock_gettime(CLOCK_MONOTONIC, &time); -# endif - return time; -} - -timespec -timespec_from_ms (const uint32_t millis) -{ - timespec time; - time.tv_sec = millis / 1e3; - time.tv_nsec = (millis - (time.tv_sec * 1e3)) * 1e6; - return time; -} - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (false), rtscts_ (false), - baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - pthread_mutex_init(&this->read_mutex, NULL); - pthread_mutex_init(&this->write_mutex, NULL); - if (port_.empty () == false) - open (); -} - -Serial::SerialImpl::~SerialImpl () -{ - close(); - pthread_mutex_destroy(&this->read_mutex); - pthread_mutex_destroy(&this->write_mutex); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty ()) { - throw invalid_argument ("Empty port is invalid."); - } - if (is_open_ == true) { - throw SerialException ("Serial port already open."); - } - - fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); - - if (fd_ == -1) { - switch (errno) { - case EINTR: - // Recurse because this is a recoverable error. - open (); - return; - case ENFILE: - case EMFILE: - THROW (IOException, "Too many file handles open."); - default: - THROW (IOException, errno); - } - } - - reconfigurePort(); - is_open_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == -1) { - // Can only operate on a valid file descriptor - THROW (IOException, "Invalid file descriptor, is the serial port open?"); - } - - struct termios options; // The options for the file descriptor - - if (tcgetattr(fd_, &options) == -1) { - THROW (IOException, "::tcgetattr"); - } - - // set up raw mode / no echo / binary - options.c_cflag |= (tcflag_t) (CLOCAL | CREAD); - options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | - ISIG | IEXTEN); //|ECHOPRT - - options.c_oflag &= (tcflag_t) ~(OPOST); - options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK); -#ifdef IUCLC - options.c_iflag &= (tcflag_t) ~IUCLC; -#endif -#ifdef PARMRK - options.c_iflag &= (tcflag_t) ~PARMRK; -#endif - - // setup baud rate - bool custom_baud = false; - speed_t baud; - switch (baudrate_) { -#ifdef B0 - case 0: baud = B0; break; -#endif -#ifdef B50 - case 50: baud = B50; break; -#endif -#ifdef B75 - case 75: baud = B75; break; -#endif -#ifdef B110 - case 110: baud = B110; break; -#endif -#ifdef B134 - case 134: baud = B134; break; -#endif -#ifdef B150 - case 150: baud = B150; break; -#endif -#ifdef B200 - case 200: baud = B200; break; -#endif -#ifdef B300 - case 300: baud = B300; break; -#endif -#ifdef B600 - case 600: baud = B600; break; -#endif -#ifdef B1200 - case 1200: baud = B1200; break; -#endif -#ifdef B1800 - case 1800: baud = B1800; break; -#endif -#ifdef B2400 - case 2400: baud = B2400; break; -#endif -#ifdef B4800 - case 4800: baud = B4800; break; -#endif -#ifdef B7200 - case 7200: baud = B7200; break; -#endif -#ifdef B9600 - case 9600: baud = B9600; break; -#endif -#ifdef B14400 - case 14400: baud = B14400; break; -#endif -#ifdef B19200 - case 19200: baud = B19200; break; -#endif -#ifdef B28800 - case 28800: baud = B28800; break; -#endif -#ifdef B57600 - case 57600: baud = B57600; break; -#endif -#ifdef B76800 - case 76800: baud = B76800; break; -#endif -#ifdef B38400 - case 38400: baud = B38400; break; -#endif -#ifdef B115200 - case 115200: baud = B115200; break; -#endif -#ifdef B128000 - case 128000: baud = B128000; break; -#endif -#ifdef B153600 - case 153600: baud = B153600; break; -#endif -#ifdef B230400 - case 230400: baud = B230400; break; -#endif -#ifdef B256000 - case 256000: baud = B256000; break; -#endif -#ifdef B460800 - case 460800: baud = B460800; break; -#endif -#ifdef B576000 - case 576000: baud = B576000; break; -#endif -#ifdef B921600 - case 921600: baud = B921600; break; -#endif -#ifdef B1000000 - case 1000000: baud = B1000000; break; -#endif -#ifdef B1152000 - case 1152000: baud = B1152000; break; -#endif -#ifdef B1500000 - case 1500000: baud = B1500000; break; -#endif -#ifdef B2000000 - case 2000000: baud = B2000000; break; -#endif -#ifdef B2500000 - case 2500000: baud = B2500000; break; -#endif -#ifdef B3000000 - case 3000000: baud = B3000000; break; -#endif -#ifdef B3500000 - case 3500000: baud = B3500000; break; -#endif -#ifdef B4000000 - case 4000000: baud = B4000000; break; -#endif - default: - custom_baud = true; - // OS X support -#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) - // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates - // other than those specified by POSIX. The driver for the underlying serial hardware - // ultimately determines which baud rates can be used. This ioctl sets both the input - // and output speed. - speed_t new_baud = static_cast (baudrate_); - if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) { - THROW (IOException, errno); - } - // Linux Support -#elif defined(__linux__) && defined (TIOCSSERIAL) - struct serial_struct ser; - - if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) { - THROW (IOException, errno); - } - - // set custom divisor - ser.custom_divisor = ser.baud_base / static_cast (baudrate_); - // update flags - ser.flags &= ~ASYNC_SPD_MASK; - ser.flags |= ASYNC_SPD_CUST; - - if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) { - THROW (IOException, errno); - } -#else - throw invalid_argument ("OS does not currently support custom bauds"); -#endif - } - if (custom_baud == false) { -#ifdef _BSD_SOURCE - ::cfsetspeed(&options, baud); -#else - ::cfsetispeed(&options, baud); - ::cfsetospeed(&options, baud); -#endif - } - - // setup char len - options.c_cflag &= (tcflag_t) ~CSIZE; - if (bytesize_ == eightbits) - options.c_cflag |= CS8; - else if (bytesize_ == sevenbits) - options.c_cflag |= CS7; - else if (bytesize_ == sixbits) - options.c_cflag |= CS6; - else if (bytesize_ == fivebits) - options.c_cflag |= CS5; - else - throw invalid_argument ("invalid char len"); - // setup stopbits - if (stopbits_ == stopbits_one) - options.c_cflag &= (tcflag_t) ~(CSTOPB); - else if (stopbits_ == stopbits_one_point_five) - // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 - options.c_cflag |= (CSTOPB); - else if (stopbits_ == stopbits_two) - options.c_cflag |= (CSTOPB); - else - throw invalid_argument ("invalid stop bit"); - // setup parity - options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP); - if (parity_ == parity_none) { - options.c_cflag &= (tcflag_t) ~(PARENB | PARODD); - } else if (parity_ == parity_even) { - options.c_cflag &= (tcflag_t) ~(PARODD); - options.c_cflag |= (PARENB); - } else if (parity_ == parity_odd) { - options.c_cflag |= (PARENB | PARODD); - } -#ifdef CMSPAR - else if (parity_ == parity_mark) { - options.c_cflag |= (PARENB | CMSPAR | PARODD); - } - else if (parity_ == parity_space) { - options.c_cflag |= (PARENB | CMSPAR); - options.c_cflag &= (tcflag_t) ~(PARODD); - } -#else - // CMSPAR is not defined on OSX. So do not support mark or space parity. - else if (parity_ == parity_mark || parity_ == parity_space) { - throw invalid_argument ("OS does not support mark or space parity"); - } -#endif // ifdef CMSPAR - else { - throw invalid_argument ("invalid parity"); - } - // setup flow control - if (flowcontrol_ == flowcontrol_none) { - xonxoff_ = false; - rtscts_ = false; - } - if (flowcontrol_ == flowcontrol_software) { - xonxoff_ = true; - rtscts_ = false; - } - if (flowcontrol_ == flowcontrol_hardware) { - xonxoff_ = false; - rtscts_ = true; - } - // xonxoff -#ifdef IXANY - if (xonxoff_) - options.c_iflag |= (IXON | IXOFF); //|IXANY) - else - options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY); -#else - if (xonxoff_) - options.c_iflag |= (IXON | IXOFF); - else - options.c_iflag &= (tcflag_t) ~(IXON | IXOFF); -#endif - // rtscts -#ifdef CRTSCTS - if (rtscts_) - options.c_cflag |= (CRTSCTS); - else - options.c_cflag &= (unsigned long) ~(CRTSCTS); -#elif defined CNEW_RTSCTS - if (rtscts_) - options.c_cflag |= (CNEW_RTSCTS); - else - options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS); -#else -#error "OS Support seems wrong." -#endif - - // http://www.unixwiz.net/techtips/termios-vmin-vtime.html - // this basically sets the read call up to be a polling read, - // but we are using select to ensure there is data available - // to read before each call, so we should never needlessly poll - options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 0; - - // activate settings - ::tcsetattr (fd_, TCSANOW, &options); - - // Update byte_time_ based on the new settings. - uint32_t bit_time_ns = 1e9 / baudrate_; - byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_); - - // Compensate for the stopbits_one_point_five enum being equal to int 3, - // and not 1.5. - if (stopbits_ == stopbits_one_point_five) { - byte_time_ns_ += ((1.5 - stopbits_one_point_five) * bit_time_ns); - } -} - -void -Serial::SerialImpl::close () -{ - if (is_open_ == true) { - if (fd_ != -1) { - int ret; - ret = ::close (fd_); - if (ret == 0) { - fd_ = -1; - } else { - THROW (IOException, errno); - } - } - is_open_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return is_open_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!is_open_) { - return 0; - } - int count = 0; - if (-1 == ioctl (fd_, TIOCINQ, &count)) { - THROW (IOException, errno); - } else { - return static_cast (count); - } -} - -bool -Serial::SerialImpl::waitReadable (uint32_t timeout) -{ - // Setup a select call to block for serial data or a timeout - fd_set readfds; - FD_ZERO (&readfds); - FD_SET (fd_, &readfds); - timespec timeout_ts (timespec_from_ms (timeout)); - int r = pselect (fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL); - - if (r < 0) { - // Select was interrupted - if (errno == EINTR) { - return false; - } - // Otherwise there was some error - THROW (IOException, errno); - } - // Timeout occurred - if (r == 0) { - return false; - } - // This shouldn't happen, if r > 0 our fd has to be in the list! - if (!FD_ISSET (fd_, &readfds)) { - THROW (IOException, "select reports ready to read, but our fd isn't" - " in the list, this shouldn't happen!"); - } - // Data available to read. - return true; -} - -void -Serial::SerialImpl::waitByteTimes (size_t count) -{ - timespec wait_time = { 0, static_cast(byte_time_ns_ * count)}; - pselect (0, NULL, NULL, NULL, &wait_time, NULL); -} - -size_t -Serial::SerialImpl::read (uint8_t *buf, size_t size) -{ - // If the port is not open, throw - if (!is_open_) { - throw PortNotOpenedException ("Serial::read"); - } - size_t bytes_read = 0; - - // Calculate total timeout in milliseconds t_c + (t_m * N) - long total_timeout_ms = timeout_.read_timeout_constant; - total_timeout_ms += timeout_.read_timeout_multiplier * static_cast (size); - MillisecondTimer total_timeout(total_timeout_ms); - - // Pre-fill buffer with available bytes - { - ssize_t bytes_read_now = ::read (fd_, buf, size); - if (bytes_read_now > 0) { - bytes_read = bytes_read_now; - } - } - - while (bytes_read < size) { - int64_t timeout_remaining_ms = total_timeout.remaining(); - if (timeout_remaining_ms <= 0) { - // Timed out - break; - } - // Timeout for the next select is whichever is less of the remaining - // total read timeout and the inter-byte timeout. - uint32_t timeout = std::min(static_cast (timeout_remaining_ms), - timeout_.inter_byte_timeout); - // Wait for the device to be readable, and then attempt to read. - if (waitReadable(timeout)) { - // If it's a fixed-length multi-byte read, insert a wait here so that - // we can attempt to grab the whole thing in a single IO call. Skip - // this wait if a non-max inter_byte_timeout is specified. - if (size > 1 && timeout_.inter_byte_timeout == Timeout::max()) { - size_t bytes_available = available(); - if (bytes_available + bytes_read < size) { - waitByteTimes(size - (bytes_available + bytes_read)); - } - } - // This should be non-blocking returning only what is available now - // Then returning so that select can block again. - ssize_t bytes_read_now = - ::read (fd_, buf + bytes_read, size - bytes_read); - // read should always return some data as select reported it was - // ready to read when we get to this point. - if (bytes_read_now < 1) { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to read immediately - // but reading returns nothing. - throw SerialException ("device reports readiness to read but " - "returned no data (device disconnected?)"); - } - // Update bytes_read - bytes_read += static_cast (bytes_read_now); - // If bytes_read == size then we have read everything we need - if (bytes_read == size) { - break; - } - // If bytes_read < size then we have more to read - if (bytes_read < size) { - continue; - } - // If bytes_read > size then we have over read, which shouldn't happen - if (bytes_read > size) { - throw SerialException ("read over read, too many bytes where " - "read, this shouldn't happen, might be " - "a logical error!"); - } - } - } - return bytes_read; -} - -size_t -Serial::SerialImpl::write (const uint8_t *data, size_t length) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::write"); - } - fd_set writefds; - size_t bytes_written = 0; - - // Calculate total timeout in milliseconds t_c + (t_m * N) - long total_timeout_ms = timeout_.write_timeout_constant; - total_timeout_ms += timeout_.write_timeout_multiplier * static_cast (length); - MillisecondTimer total_timeout(total_timeout_ms); - - bool first_iteration = true; - while (bytes_written < length) { - int64_t timeout_remaining_ms = total_timeout.remaining(); - // Only consider the timeout if it's not the first iteration of the loop - // otherwise a timeout of 0 won't be allowed through - if (!first_iteration && (timeout_remaining_ms <= 0)) { - // Timed out - break; - } - first_iteration = false; - - timespec timeout(timespec_from_ms(timeout_remaining_ms)); - - FD_ZERO (&writefds); - FD_SET (fd_, &writefds); - - // Do the select - int r = pselect (fd_ + 1, NULL, &writefds, NULL, &timeout, NULL); - - // Figure out what happened by looking at select's response 'r' - /** Error **/ - if (r < 0) { - // Select was interrupted, try again - if (errno == EINTR) { - continue; - } - // Otherwise there was some error - THROW (IOException, errno); - } - /** Timeout **/ - if (r == 0) { - break; - } - /** Port ready to write **/ - if (r > 0) { - // Make sure our file descriptor is in the ready to write list - if (FD_ISSET (fd_, &writefds)) { - // This will write some - ssize_t bytes_written_now = - ::write (fd_, data + bytes_written, length - bytes_written); - // write should always return some data as select reported it was - // ready to write when we get to this point. - if (bytes_written_now < 1) { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to write immediately - // but writing returns nothing. - throw SerialException ("device reports readiness to write but " - "returned no data (device disconnected?)"); - } - // Update bytes_written - bytes_written += static_cast (bytes_written_now); - // If bytes_written == size then we have written everything we need to - if (bytes_written == length) { - break; - } - // If bytes_written < size then we have more to write - if (bytes_written < length) { - continue; - } - // If bytes_written > size then we have over written, which shouldn't happen - if (bytes_written > length) { - throw SerialException ("write over wrote, too many bytes where " - "written, this shouldn't happen, might be " - "a logical error!"); - } - } - // This shouldn't happen, if r > 0 our fd has to be in the list! - THROW (IOException, "select reports ready to write, but our fd isn't" - " in the list, this shouldn't happen!"); - } - } - return bytes_written; -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = port; -} - -string -Serial::SerialImpl::getPort () const -{ - return port_; -} - -void -Serial::SerialImpl::setTimeout (serial::Timeout &timeout) -{ - timeout_ = timeout; -} - -serial::Timeout -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (is_open_) - reconfigurePort (); -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (is_open_) - reconfigurePort (); -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (is_open_) - reconfigurePort (); -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (is_open_) - reconfigurePort (); -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (is_open_) - reconfigurePort (); -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flush"); - } - tcdrain (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flushInput"); - } - tcflush (fd_, TCIFLUSH); -} - -void -Serial::SerialImpl::flushOutput () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flushOutput"); - } - tcflush (fd_, TCOFLUSH); -} - -void -Serial::SerialImpl::sendBreak (int duration) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::sendBreak"); - } - tcsendbreak (fd_, static_cast (duration / 4)); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setBreak"); - } - - if (level) { - if (-1 == ioctl (fd_, TIOCSBRK)) - { - stringstream ss; - ss << "setBreak failed on a call to ioctl(TIOCSBRK): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCCBRK)) - { - stringstream ss; - ss << "setBreak failed on a call to ioctl(TIOCCBRK): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setRTS"); - } - - int command = TIOCM_RTS; - - if (level) { - if (-1 == ioctl (fd_, TIOCMBIS, &command)) - { - stringstream ss; - ss << "setRTS failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCMBIC, &command)) - { - stringstream ss; - ss << "setRTS failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setDTR"); - } - - int command = TIOCM_DTR; - - if (level) { - if (-1 == ioctl (fd_, TIOCMBIS, &command)) - { - stringstream ss; - ss << "setDTR failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCMBIC, &command)) - { - stringstream ss; - ss << "setDTR failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -bool -Serial::SerialImpl::waitForChange () -{ -#ifndef TIOCMIWAIT - -while (is_open_ == true) { - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "waitForChange failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - if (0 != (status & TIOCM_CTS) - || 0 != (status & TIOCM_DSR) - || 0 != (status & TIOCM_RI) - || 0 != (status & TIOCM_CD)) - { - return true; - } - } - - usleep(1000); - } - - return false; -#else - int command = (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS); - - if (-1 == ioctl (fd_, TIOCMIWAIT, &command)) { - stringstream ss; - ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): " - << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - return true; -#endif -} - -bool -Serial::SerialImpl::getCTS () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCTS"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getCTS failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_CTS); - } -} - -bool -Serial::SerialImpl::getDSR () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getDSR"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getDSR failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_DSR); - } -} - -bool -Serial::SerialImpl::getRI () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getRI"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getRI failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_RI); - } -} - -bool -Serial::SerialImpl::getCD () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCD"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getCD failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_CD); - } -} - -void -Serial::SerialImpl::readLock () -{ - int result = pthread_mutex_lock(&this->read_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::readUnlock () -{ - int result = pthread_mutex_unlock(&this->read_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::writeLock () -{ - int result = pthread_mutex_lock(&this->write_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::writeUnlock () -{ - int result = pthread_mutex_unlock(&this->write_mutex); - if (result) { - THROW (IOException, result); - } -} - -#endif // !defined(_WIN32) diff --git a/code/c++/cxx-api/serial_support/src/impl/win.cc b/code/c++/cxx-api/serial_support/src/impl/win.cc deleted file mode 100644 index 3446160..0000000 --- a/code/c++/cxx-api/serial_support/src/impl/win.cc +++ /dev/null @@ -1,640 +0,0 @@ -#if defined(_WIN32) - -/* Copyright 2012 William Woodall and John Harrison */ - -#include - -#include "serial/impl/win.h" - -using std::string; -using std::wstring; -using std::stringstream; -using std::invalid_argument; -using serial::Serial; -using serial::Timeout; -using serial::bytesize_t; -using serial::parity_t; -using serial::stopbits_t; -using serial::flowcontrol_t; -using serial::SerialException; -using serial::PortNotOpenedException; -using serial::IOException; - -inline wstring -_prefix_port_if_needed(const wstring &input) -{ - static wstring windows_com_port_prefix = L"\\\\.\\"; - if (input.compare(windows_com_port_prefix) != 0) - { - return windows_com_port_prefix + input; - } - return input; -} - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false), - baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - if (port_.empty () == false) - open (); - read_mutex = CreateMutex(NULL, false, NULL); - write_mutex = CreateMutex(NULL, false, NULL); -} - -Serial::SerialImpl::~SerialImpl () -{ - this->close(); - CloseHandle(read_mutex); - CloseHandle(write_mutex); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty ()) { - throw invalid_argument ("Empty port is invalid."); - } - if (is_open_ == true) { - throw SerialException ("Serial port already open."); - } - - // See: https://github.com/wjwwood/serial/issues/84 - wstring port_with_prefix = _prefix_port_if_needed(port_); - LPCWSTR lp_port = port_with_prefix.c_str(); - fd_ = CreateFileW(lp_port, - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0); - - if (fd_ == INVALID_HANDLE_VALUE) { - DWORD errno_ = GetLastError(); - stringstream ss; - switch (errno_) { - case ERROR_FILE_NOT_FOUND: - // Use this->getPort to convert to a std::string - ss << "Specified port, " << this->getPort() << ", does not exist."; - THROW (IOException, ss.str().c_str()); - default: - ss << "Unknown error opening the serial port: " << errno; - THROW (IOException, ss.str().c_str()); - } - } - - reconfigurePort(); - is_open_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == INVALID_HANDLE_VALUE) { - // Can only operate on a valid file descriptor - THROW (IOException, "Invalid file descriptor, is the serial port open?"); - } - - DCB dcbSerialParams = {0}; - - dcbSerialParams.DCBlength=sizeof(dcbSerialParams); - - if (!GetCommState(fd_, &dcbSerialParams)) { - //error getting state - THROW (IOException, "Error getting the serial port state."); - } - - // setup baud rate - switch (baudrate_) { -#ifdef CBR_0 - case 0: dcbSerialParams.BaudRate = CBR_0; break; -#endif -#ifdef CBR_50 - case 50: dcbSerialParams.BaudRate = CBR_50; break; -#endif -#ifdef CBR_75 - case 75: dcbSerialParams.BaudRate = CBR_75; break; -#endif -#ifdef CBR_110 - case 110: dcbSerialParams.BaudRate = CBR_110; break; -#endif -#ifdef CBR_134 - case 134: dcbSerialParams.BaudRate = CBR_134; break; -#endif -#ifdef CBR_150 - case 150: dcbSerialParams.BaudRate = CBR_150; break; -#endif -#ifdef CBR_200 - case 200: dcbSerialParams.BaudRate = CBR_200; break; -#endif -#ifdef CBR_300 - case 300: dcbSerialParams.BaudRate = CBR_300; break; -#endif -#ifdef CBR_600 - case 600: dcbSerialParams.BaudRate = CBR_600; break; -#endif -#ifdef CBR_1200 - case 1200: dcbSerialParams.BaudRate = CBR_1200; break; -#endif -#ifdef CBR_1800 - case 1800: dcbSerialParams.BaudRate = CBR_1800; break; -#endif -#ifdef CBR_2400 - case 2400: dcbSerialParams.BaudRate = CBR_2400; break; -#endif -#ifdef CBR_4800 - case 4800: dcbSerialParams.BaudRate = CBR_4800; break; -#endif -#ifdef CBR_7200 - case 7200: dcbSerialParams.BaudRate = CBR_7200; break; -#endif -#ifdef CBR_9600 - case 9600: dcbSerialParams.BaudRate = CBR_9600; break; -#endif -#ifdef CBR_14400 - case 14400: dcbSerialParams.BaudRate = CBR_14400; break; -#endif -#ifdef CBR_19200 - case 19200: dcbSerialParams.BaudRate = CBR_19200; break; -#endif -#ifdef CBR_28800 - case 28800: dcbSerialParams.BaudRate = CBR_28800; break; -#endif -#ifdef CBR_57600 - case 57600: dcbSerialParams.BaudRate = CBR_57600; break; -#endif -#ifdef CBR_76800 - case 76800: dcbSerialParams.BaudRate = CBR_76800; break; -#endif -#ifdef CBR_38400 - case 38400: dcbSerialParams.BaudRate = CBR_38400; break; -#endif -#ifdef CBR_115200 - case 115200: dcbSerialParams.BaudRate = CBR_115200; break; -#endif -#ifdef CBR_128000 - case 128000: dcbSerialParams.BaudRate = CBR_128000; break; -#endif -#ifdef CBR_153600 - case 153600: dcbSerialParams.BaudRate = CBR_153600; break; -#endif -#ifdef CBR_230400 - case 230400: dcbSerialParams.BaudRate = CBR_230400; break; -#endif -#ifdef CBR_256000 - case 256000: dcbSerialParams.BaudRate = CBR_256000; break; -#endif -#ifdef CBR_460800 - case 460800: dcbSerialParams.BaudRate = CBR_460800; break; -#endif -#ifdef CBR_921600 - case 921600: dcbSerialParams.BaudRate = CBR_921600; break; -#endif - default: - // Try to blindly assign it - dcbSerialParams.BaudRate = baudrate_; - } - - // setup char len - if (bytesize_ == eightbits) - dcbSerialParams.ByteSize = 8; - else if (bytesize_ == sevenbits) - dcbSerialParams.ByteSize = 7; - else if (bytesize_ == sixbits) - dcbSerialParams.ByteSize = 6; - else if (bytesize_ == fivebits) - dcbSerialParams.ByteSize = 5; - else - throw invalid_argument ("invalid char len"); - - // setup stopbits - if (stopbits_ == stopbits_one) - dcbSerialParams.StopBits = ONESTOPBIT; - else if (stopbits_ == stopbits_one_point_five) - dcbSerialParams.StopBits = ONE5STOPBITS; - else if (stopbits_ == stopbits_two) - dcbSerialParams.StopBits = TWOSTOPBITS; - else - throw invalid_argument ("invalid stop bit"); - - // setup parity - if (parity_ == parity_none) { - dcbSerialParams.Parity = NOPARITY; - } else if (parity_ == parity_even) { - dcbSerialParams.Parity = EVENPARITY; - } else if (parity_ == parity_odd) { - dcbSerialParams.Parity = ODDPARITY; - } else if (parity_ == parity_mark) { - dcbSerialParams.Parity = MARKPARITY; - } else if (parity_ == parity_space) { - dcbSerialParams.Parity = SPACEPARITY; - } else { - throw invalid_argument ("invalid parity"); - } - - // setup flowcontrol - if (flowcontrol_ == flowcontrol_none) { - dcbSerialParams.fOutxCtsFlow = false; - dcbSerialParams.fRtsControl = 0x00; - dcbSerialParams.fOutX = false; - dcbSerialParams.fInX = false; - } - if (flowcontrol_ == flowcontrol_software) { - dcbSerialParams.fOutxCtsFlow = false; - dcbSerialParams.fRtsControl = 0x00; - dcbSerialParams.fOutX = true; - dcbSerialParams.fInX = true; - } - if (flowcontrol_ == flowcontrol_hardware) { - dcbSerialParams.fOutxCtsFlow = true; - dcbSerialParams.fRtsControl = 0x03; - dcbSerialParams.fOutX = false; - dcbSerialParams.fInX = false; - } - - // activate settings - if (!SetCommState(fd_, &dcbSerialParams)){ - CloseHandle(fd_); - THROW (IOException, "Error setting serial port settings."); - } - - // Setup timeouts - COMMTIMEOUTS timeouts = {0}; - timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout; - timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant; - timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier; - timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant; - timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier; - if (!SetCommTimeouts(fd_, &timeouts)) { - THROW (IOException, "Error setting timeouts."); - } -} - -void -Serial::SerialImpl::close () -{ - if (is_open_ == true) { - if (fd_ != INVALID_HANDLE_VALUE) { - int ret; - ret = CloseHandle(fd_); - if (ret == 0) { - stringstream ss; - ss << "Error while closing serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } else { - fd_ = INVALID_HANDLE_VALUE; - } - } - is_open_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return is_open_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!is_open_) { - return 0; - } - COMSTAT cs; - if (!ClearCommError(fd_, NULL, &cs)) { - stringstream ss; - ss << "Error while checking status of the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return static_cast(cs.cbInQue); -} - -bool -Serial::SerialImpl::waitReadable (uint32_t /*timeout*/) -{ - THROW (IOException, "waitReadable is not implemented on Windows."); - return false; -} - -void -Serial::SerialImpl::waitByteTimes (size_t /*count*/) -{ - THROW (IOException, "waitByteTimes is not implemented on Windows."); -} - -size_t -Serial::SerialImpl::read (uint8_t *buf, size_t size) -{ - if (!is_open_) { - throw PortNotOpenedException ("Serial::read"); - } - DWORD bytes_read; - if (!ReadFile(fd_, buf, static_cast(size), &bytes_read, NULL)) { - stringstream ss; - ss << "Error while reading from the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return (size_t) (bytes_read); -} - -size_t -Serial::SerialImpl::write (const uint8_t *data, size_t length) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::write"); - } - DWORD bytes_written; - if (!WriteFile(fd_, data, static_cast(length), &bytes_written, NULL)) { - stringstream ss; - ss << "Error while writing to the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return (size_t) (bytes_written); -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = wstring(port.begin(), port.end()); -} - -string -Serial::SerialImpl::getPort () const -{ - return string(port_.begin(), port_.end()); -} - -void -Serial::SerialImpl::setTimeout (serial::Timeout &timeout) -{ - timeout_ = timeout; - if (is_open_) { - reconfigurePort (); - } -} - -serial::Timeout -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (is_open_) { - reconfigurePort (); - } -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (is_open_) { - reconfigurePort (); - } -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (is_open_) { - reconfigurePort (); - } -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (is_open_) { - reconfigurePort (); - } -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (is_open_) { - reconfigurePort (); - } -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flush"); - } - FlushFileBuffers (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - THROW (IOException, "flushInput is not supported on Windows."); -} - -void -Serial::SerialImpl::flushOutput () -{ - THROW (IOException, "flushOutput is not supported on Windows."); -} - -void -Serial::SerialImpl::sendBreak (int /*duration*/) -{ - THROW (IOException, "sendBreak is not supported on Windows."); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setBreak"); - } - if (level) { - EscapeCommFunction (fd_, SETBREAK); - } else { - EscapeCommFunction (fd_, CLRBREAK); - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setRTS"); - } - if (level) { - EscapeCommFunction (fd_, SETRTS); - } else { - EscapeCommFunction (fd_, CLRRTS); - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setDTR"); - } - if (level) { - EscapeCommFunction (fd_, SETDTR); - } else { - EscapeCommFunction (fd_, CLRDTR); - } -} - -bool -Serial::SerialImpl::waitForChange () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::waitForChange"); - } - DWORD dwCommEvent; - - if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) { - // Error setting communications mask - return false; - } - - if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) { - // An error occurred waiting for the event. - return false; - } else { - // Event has occurred. - return true; - } -} - -bool -Serial::SerialImpl::getCTS () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCTS"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the CTS line."); - } - - return (MS_CTS_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getDSR () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getDSR"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the DSR line."); - } - - return (MS_DSR_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getRI() -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getRI"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the RI line."); - } - - return (MS_RING_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getCD() -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCD"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - // Error in GetCommModemStatus; - THROW (IOException, "Error getting the status of the CD line."); - } - - return (MS_RLSD_ON & dwModemStatus) != 0; -} - -void -Serial::SerialImpl::readLock() -{ - if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) { - THROW (IOException, "Error claiming read mutex."); - } -} - -void -Serial::SerialImpl::readUnlock() -{ - if (!ReleaseMutex(read_mutex)) { - THROW (IOException, "Error releasing read mutex."); - } -} - -void -Serial::SerialImpl::writeLock() -{ - if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) { - THROW (IOException, "Error claiming write mutex."); - } -} - -void -Serial::SerialImpl::writeUnlock() -{ - if (!ReleaseMutex(write_mutex)) { - THROW (IOException, "Error releasing write mutex."); - } -} - -#endif // #if defined(_WIN32) - diff --git a/code/c++/cxx-api/serial_support/src/serial.cc b/code/c++/cxx-api/serial_support/src/serial.cc deleted file mode 100644 index aab4caa..0000000 --- a/code/c++/cxx-api/serial_support/src/serial.cc +++ /dev/null @@ -1,414 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison */ -#include - -#if !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__) -# include -#endif - -#if defined (__MINGW32__) -# define alloca __builtin_alloca -#endif - -#include "serial/serial.h" - -#ifdef _WIN32 -#include "serial/impl/win.h" -#else -#include "serial/impl/unix.h" -#endif - -using std::invalid_argument; -using std::min; -using std::numeric_limits; -using std::vector; -using std::size_t; -using std::string; - -using serial::Serial; -using serial::SerialException; -using serial::IOException; -using serial::bytesize_t; -using serial::parity_t; -using serial::stopbits_t; -using serial::flowcontrol_t; - -class Serial::ScopedReadLock { -public: - ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) { - this->pimpl_->readLock(); - } - ~ScopedReadLock() { - this->pimpl_->readUnlock(); - } -private: - // Disable copy constructors - ScopedReadLock(const ScopedReadLock&); - const ScopedReadLock& operator=(ScopedReadLock); - - SerialImpl *pimpl_; -}; - -class Serial::ScopedWriteLock { -public: - ScopedWriteLock(SerialImpl *pimpl) : pimpl_(pimpl) { - this->pimpl_->writeLock(); - } - ~ScopedWriteLock() { - this->pimpl_->writeUnlock(); - } -private: - // Disable copy constructors - ScopedWriteLock(const ScopedWriteLock&); - const ScopedWriteLock& operator=(ScopedWriteLock); - SerialImpl *pimpl_; -}; - -Serial::Serial (const string &port, uint32_t baudrate, serial::Timeout timeout, - bytesize_t bytesize, parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : pimpl_(new SerialImpl (port, baudrate, bytesize, parity, - stopbits, flowcontrol)) -{ - pimpl_->setTimeout(timeout); -} - -Serial::~Serial () -{ - delete pimpl_; -} - -void -Serial::open () -{ - pimpl_->open (); -} - -void -Serial::close () -{ - pimpl_->close (); -} - -bool -Serial::isOpen () const -{ - return pimpl_->isOpen (); -} - -size_t -Serial::available () -{ - return pimpl_->available (); -} - -bool -Serial::waitReadable () -{ - serial::Timeout timeout(pimpl_->getTimeout ()); - return pimpl_->waitReadable(timeout.read_timeout_constant); -} - -void -Serial::waitByteTimes (size_t count) -{ - pimpl_->waitByteTimes(count); -} - -size_t -Serial::read_ (uint8_t *buffer, size_t size) -{ - return this->pimpl_->read (buffer, size); -} - -size_t -Serial::read (uint8_t *buffer, size_t size) -{ - ScopedReadLock lock(this->pimpl_); - return this->pimpl_->read (buffer, size); -} - -size_t -Serial::read (std::vector &buffer, size_t size) -{ - ScopedReadLock lock(this->pimpl_); - uint8_t *buffer_ = new uint8_t[size]; - size_t bytes_read = this->pimpl_->read (buffer_, size); - buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); - delete[] buffer_; - return bytes_read; -} - -size_t -Serial::read (std::string &buffer, size_t size) -{ - ScopedReadLock lock(this->pimpl_); - uint8_t *buffer_ = new uint8_t[size]; - size_t bytes_read = this->pimpl_->read (buffer_, size); - buffer.append (reinterpret_cast(buffer_), bytes_read); - delete[] buffer_; - return bytes_read; -} - -string -Serial::read (size_t size) -{ - std::string buffer; - this->read (buffer, size); - return buffer; -} - -size_t -Serial::readline (string &buffer, size_t size, string eol) -{ - ScopedReadLock lock(this->pimpl_); - size_t eol_len = eol.length (); - uint8_t *buffer_ = static_cast - (alloca (size * sizeof (uint8_t))); - size_t read_so_far = 0; - while (true) - { - size_t bytes_read = this->read_ (buffer_ + read_so_far, 1); - read_so_far += bytes_read; - if (bytes_read == 0) { - break; // Timeout occured on reading 1 byte - } - if (string (reinterpret_cast - (buffer_ + read_so_far - eol_len), eol_len) == eol) { - break; // EOL found - } - if (read_so_far == size) { - break; // Reached the maximum read length - } - } - buffer.append(reinterpret_cast (buffer_), read_so_far); - return read_so_far; -} - -string -Serial::readline (size_t size, string eol) -{ - std::string buffer; - this->readline (buffer, size, eol); - return buffer; -} - -vector -Serial::readlines (size_t size, string eol) -{ - ScopedReadLock lock(this->pimpl_); - std::vector lines; - size_t eol_len = eol.length (); - uint8_t *buffer_ = static_cast - (alloca (size * sizeof (uint8_t))); - size_t read_so_far = 0; - size_t start_of_line = 0; - while (read_so_far < size) { - size_t bytes_read = this->read_ (buffer_+read_so_far, 1); - read_so_far += bytes_read; - if (bytes_read == 0) { - if (start_of_line != read_so_far) { - lines.push_back ( - string (reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - } - break; // Timeout occured on reading 1 byte - } - if (string (reinterpret_cast - (buffer_ + read_so_far - eol_len), eol_len) == eol) { - // EOL found - lines.push_back( - string(reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - start_of_line = read_so_far; - } - if (read_so_far == size) { - if (start_of_line != read_so_far) { - lines.push_back( - string(reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - } - break; // Reached the maximum read length - } - } - return lines; -} - -size_t -Serial::write (const string &data) -{ - ScopedWriteLock lock(this->pimpl_); - return this->write_ (reinterpret_cast(data.c_str()), - data.length()); -} - -size_t -Serial::write (const std::vector &data) -{ - ScopedWriteLock lock(this->pimpl_); - return this->write_ (&data[0], data.size()); -} - -size_t -Serial::write (const uint8_t *data, size_t size) -{ - ScopedWriteLock lock(this->pimpl_); - return this->write_(data, size); -} - -size_t -Serial::write_ (const uint8_t *data, size_t length) -{ - return pimpl_->write (data, length); -} - -void -Serial::setPort (const string &port) -{ - ScopedReadLock rlock(this->pimpl_); - ScopedWriteLock wlock(this->pimpl_); - bool was_open = pimpl_->isOpen (); - if (was_open) close(); - pimpl_->setPort (port); - if (was_open) open (); -} - -string -Serial::getPort () const -{ - return pimpl_->getPort (); -} - -void -Serial::setTimeout (serial::Timeout &timeout) -{ - pimpl_->setTimeout (timeout); -} - -serial::Timeout -Serial::getTimeout () const { - return pimpl_->getTimeout (); -} - -void -Serial::setBaudrate (uint32_t baudrate) -{ - pimpl_->setBaudrate (baudrate); -} - -uint32_t -Serial::getBaudrate () const -{ - return uint32_t(pimpl_->getBaudrate ()); -} - -void -Serial::setBytesize (bytesize_t bytesize) -{ - pimpl_->setBytesize (bytesize); -} - -bytesize_t -Serial::getBytesize () const -{ - return pimpl_->getBytesize (); -} - -void -Serial::setParity (parity_t parity) -{ - pimpl_->setParity (parity); -} - -parity_t -Serial::getParity () const -{ - return pimpl_->getParity (); -} - -void -Serial::setStopbits (stopbits_t stopbits) -{ - pimpl_->setStopbits (stopbits); -} - -stopbits_t -Serial::getStopbits () const -{ - return pimpl_->getStopbits (); -} - -void -Serial::setFlowcontrol (flowcontrol_t flowcontrol) -{ - pimpl_->setFlowcontrol (flowcontrol); -} - -flowcontrol_t -Serial::getFlowcontrol () const -{ - return pimpl_->getFlowcontrol (); -} - -void Serial::flush () -{ - ScopedReadLock rlock(this->pimpl_); - ScopedWriteLock wlock(this->pimpl_); - pimpl_->flush (); -} - -void Serial::flushInput () -{ - ScopedReadLock lock(this->pimpl_); - pimpl_->flushInput (); -} - -void Serial::flushOutput () -{ - ScopedWriteLock lock(this->pimpl_); - pimpl_->flushOutput (); -} - -void Serial::sendBreak (int duration) -{ - pimpl_->sendBreak (duration); -} - -void Serial::setBreak (bool level) -{ - pimpl_->setBreak (level); -} - -void Serial::setRTS (bool level) -{ - pimpl_->setRTS (level); -} - -void Serial::setDTR (bool level) -{ - pimpl_->setDTR (level); -} - -bool Serial::waitForChange() -{ - return pimpl_->waitForChange(); -} - -bool Serial::getCTS () -{ - return pimpl_->getCTS (); -} - -bool Serial::getDSR () -{ - return pimpl_->getDSR (); -} - -bool Serial::getRI () -{ - return pimpl_->getRI (); -} - -bool Serial::getCD () -{ - return pimpl_->getCD (); -} From fa06394a1bec07a043375b342a435a2484fcfed4 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 9 Aug 2017 11:27:11 +0300 Subject: [PATCH 030/336] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Отладочная консоль полностью может быть включена или отключена включением/отключением DEBUG_ON макроса в debugSerial.h * Для вывода информации в консоль описаны 5 макросов (рекомендуется использовать только их во ихбежании проблем) --- code/Arduino/connectors/DebugSerial.cpp | 24 ++++++++++++-- code/Arduino/connectors/DebugSerial.h | 33 +++++++++++++++++++ code/Arduino/peripheral/SensorsController.cpp | 4 +-- code/Arduino/trackPlatform.ino | 13 ++++---- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp index 97ca371..eafc714 100644 --- a/code/Arduino/connectors/DebugSerial.cpp +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -1,6 +1,9 @@ -#include "../Constants.h" +#include +#include "../Constants.h" #include "DebugSerial.h" +#ifdef DEBUG_ON + SoftwareSerial* DebugSerial::serial = DebugSerial::generateDbgSerial(); SoftwareSerial* DebugSerial::generateDbgSerial() @@ -39,7 +42,7 @@ void DebugSerial::printHex(String data) { for (int i = 0; i < data.length(); ++i) { - device->printf("%02X ", data[i]); + printf("%02X ", data[i]); } } @@ -48,3 +51,20 @@ void DebugSerial::printlnHex(String data) printHex(data); device->println(""); } + +void DebugSerial::printf(const char* format, ...) +{ + char buf[printfBuffSize] = {0}; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + for (char *p = &buf[0]; *p; p++) // emulate cooked mode for newlines + { + if (*p == '\n') + device->write('\r'); + device->write(*p); + } + va_end(ap); +} + +#endif diff --git a/code/Arduino/connectors/DebugSerial.h b/code/Arduino/connectors/DebugSerial.h index d834c75..6261754 100644 --- a/code/Arduino/connectors/DebugSerial.h +++ b/code/Arduino/connectors/DebugSerial.h @@ -3,9 +3,34 @@ #include "ConnectingDevice.h" +/** + * @brief Define, if debug is require + */ +#define DEBUG_ON + +#ifdef DEBUG_ON + +#define DEBUG_PRINT(...) DebugSerial().print(__VA_ARGS__) +#define DEBUG_PRINTLN(...) DebugSerial().println(__VA_ARGS__) +#define DEBUG_PRINTHEX(...) DebugSerial().printHex(__VA_ARGS__) +#define DEBUG_PRINTLNHEX(...) DebugSerial().printlnHex(__VA_ARGS__) +#define DEBUG_PRINTF(...) DebugSerial().printf(__VA_ARGS__) + +#else + +#define DEBUG_PRINT(...) +#define DEBUG_PRINTLN(...) +#define DEBUG_PRINTHEX(...) +#define DEBUG_PRINTLNHEX(...) +#define DEBUG_PRINTF(...) + +#endif + +#ifdef DEBUG_ON class DebugSerial : public ConnectingDevice { static SoftwareSerial* serial; + static const int printfBuffSize = 120; static SoftwareSerial* generateDbgSerial(); public: @@ -43,4 +68,12 @@ class DebugSerial : public ConnectingDevice * @param data String to print */ void printlnHex(String data); + /** + * @brief Prints data as simple printf function + * @warning No float/double support + * @warning Max buffer length (with printed values) must be less that @printBuffSize class member + */ + void printf(const char *format, ...); }; + +#endif diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index fca83c1..0abe9c2 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -128,10 +128,10 @@ void SensorsController::chooseDistanceSensor(int number) { int SensorsController::getDistance(int number) { chooseDistanceSensor(number); float volts = analogRead(constants.distance_sensor_read_pin); - DebugSerial::getSerial()->printf("Distance volts: %d\n", (int)volts); + DEBUG_PRINTF("Distance volts: %d\n", (int)volts); if (volts == 0) { - DebugSerial::getSerial()->println("Distance volts were 0"); + DEBUG_PRINTLN("Distance volts were 0"); return -1; //TODO: crutch } float distance = (6762 / (volts)) - 4; diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index be51a0b..1c67301 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -23,7 +23,6 @@ WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); USB usb; ConnectingDevice *device = nullptr; CommandsController controller; -DebugSerial debugSerial; bool connected = false; @@ -35,23 +34,23 @@ void setup() Serial.begin(Constants::usb_serial_speed); - debugSerial.println("Arduino was started"); + DEBUG_PRINTLN("Arduino was started"); while (!connected) { if (bluetooth.isActive()) { connected = true; device = &bluetooth; - debugSerial.println("Bluetooth"); + DEBUG_PRINTLN("Bluetooth"); } else if (wifi.isActive()) { connected = true; device = &wifi; - debugSerial.println("Wifi"); + DEBUG_PRINTLN("Wifi"); } else if (usb.isActive()) { connected = true; device = &usb; - debugSerial.println("USB"); + DEBUG_PRINTLN("USB"); } } } @@ -63,8 +62,8 @@ void loop() String command = device->read(); //debug - debugSerial.print("Command: "); - debugSerial.printlnHex(command); + DEBUG_PRINT("Command: "); + DEBUG_PRINTLNHEX(command); controller.handle(device, command); } From 0400c7c41ab635a8d5757efdbe754431258a89ed Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 9 Aug 2017 23:17:11 +0300 Subject: [PATCH 031/336] =?UTF-8?q?=D0=91=D0=B0=D0=B7=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=BE=D1=82=D0=BE=D1=82=D0=B8=D0=BF=D1=8B?= =?UTF-8?q?=20TCP/IP=20=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Из базового класса соединений удалены rx, tx и baudrate, он теперь обычный интерфейс (с базовой реализацией некоторых методов) * Добавлен базовый класс для TCP/IP соединения * Написан базовый конструктор для TCP/IP клиента для Windows * В cxx-app временно добавлена компиляция с TCP/IP клиентом и поправлено меню для linux --- code/c++/cxx-api/ConnectionModes.h | 1 + code/c++/cxx-api/SerialConnector.cpp | 2 +- code/c++/cxx-api/SerialConnector.h | 4 + code/c++/cxx-api/TCPIP_Connector.cpp | 90 +++++ code/c++/cxx-api/TCPIP_Connector.h | 20 + .../cxx-api/TrackPlatform_BasicConnector.cpp | 3 +- .../cxx-api/TrackPlatform_BasicConnector.h | 6 +- code/c++/cxx-api/cxx-api.vcxproj | 342 +++++++++--------- code/c++/cxx-api/cxx-api.vcxproj.filters | 178 ++++----- code/c++/cxx-app/main.cpp | 6 + 10 files changed, 388 insertions(+), 264 deletions(-) create mode 100644 code/c++/cxx-api/TCPIP_Connector.cpp create mode 100644 code/c++/cxx-api/TCPIP_Connector.h diff --git a/code/c++/cxx-api/ConnectionModes.h b/code/c++/cxx-api/ConnectionModes.h index edfebb6..3da8463 100644 --- a/code/c++/cxx-api/ConnectionModes.h +++ b/code/c++/cxx-api/ConnectionModes.h @@ -5,6 +5,7 @@ enum ConnectionModes { USB, bluetooth, + WiFi, }; #endif /* _CONNECTION_MODES_H_ */ diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index b3bb509..cbd4e9a 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -6,7 +6,7 @@ void SerialConnector::write(const std::string& s) } SerialConnector::SerialConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : - TrackPlatform_BasicConnector(rx, tx, baudRate), readPort(new serial::Serial(rx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))), + rxLocation(rx), txLocation(tx), baudRate(baudRate), readPort(new serial::Serial(rx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))), writePort((rx == tx) ? readPort : new serial::Serial(tx, baudRate, serial::Timeout::simpleTimeout(timeoutInMs))) { } diff --git a/code/c++/cxx-api/SerialConnector.h b/code/c++/cxx-api/SerialConnector.h index f06d898..a1255c5 100644 --- a/code/c++/cxx-api/SerialConnector.h +++ b/code/c++/cxx-api/SerialConnector.h @@ -9,6 +9,10 @@ class SerialConnector : public TrackPlatform_BasicConnector static const size_t messageMaxSize = 65535; static const size_t timeoutInMs = 500; + std::string rxLocation; + std::string txLocation; + uint32_t baudRate; + serial::Serial* readPort; serial::Serial* writePort; diff --git a/code/c++/cxx-api/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp new file mode 100644 index 0000000..94bae54 --- /dev/null +++ b/code/c++/cxx-api/TCPIP_Connector.cpp @@ -0,0 +1,90 @@ +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") + +#endif + +#include "TCPIP_Connector.h" + +void TCPIP_Connector::write(const std::string& s) +{ + //TODO +} + +std::string TCPIP_Connector::read() +{ + //TODO + return std::string(); +} + +bool TCPIP_Connector::isConnected() +{ + //TODO + return false; +} + +TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) + : ip(ip), port(port) +{ + //TODO + +#ifdef _WIN32 + WSADATA wsaData; + + // Initialize Winsock + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != 0) { + printf("WSAStartup failed: %d\n", iResult); + return; + //TODO: throw exception + } + + + struct addrinfo *result = NULL, + *ptr = NULL, + hints; + + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + +#define DEFAULT_PORT "27015" + + // Resolve the server address and port + iResult = getaddrinfo(ip.c_str(), DEFAULT_PORT, &hints, &result); + if (iResult != 0) { + printf("getaddrinfo failed: %d\n", iResult); + WSACleanup(); + return; + } + + SOCKET ConnectSocket = INVALID_SOCKET; + + // Attempt to connect to the first address returned by + // the call to getaddrinfo + ptr = result; + + // Create a SOCKET for connecting to server + ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, + ptr->ai_protocol); + + if (ConnectSocket == INVALID_SOCKET) { + printf("Error at socket(): %ld\n", WSAGetLastError()); + freeaddrinfo(result); + WSACleanup(); + return; + } + +#endif + +} diff --git a/code/c++/cxx-api/TCPIP_Connector.h b/code/c++/cxx-api/TCPIP_Connector.h new file mode 100644 index 0000000..a434783 --- /dev/null +++ b/code/c++/cxx-api/TCPIP_Connector.h @@ -0,0 +1,20 @@ +#ifndef _TCPIP_CONNECTOR_H_ +#define _TCPIP_CONNECTOR_H_ + +#include "TrackPlatform_BasicConnector.h" + +class TCPIP_Connector : public TrackPlatform_BasicConnector +{ + std::string ip; + uint16_t port; + +protected: + void write(const std::string& s) override; + std::string read() override; +public: + TCPIP_Connector(const std::string& ip, uint16_t port); + + bool isConnected() override; +}; + +#endif diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index 80d6a59..1e2eabe 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -1,7 +1,6 @@ #include "TrackPlatform_BasicConnector.h" -TrackPlatform_BasicConnector::TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : - rxLocation(rx), txLocation(tx), baudRate(baudRate) +TrackPlatform_BasicConnector::TrackPlatform_BasicConnector() { } diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index de5eb10..273ba14 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -6,17 +6,13 @@ class TrackPlatform_BasicConnector { protected: - std::string rxLocation; - std::string txLocation; - uint32_t baudRate; - static const char stopSymbol = '|'; virtual void write(const std::string& s) = 0; virtual std::string read() = 0; public: - TrackPlatform_BasicConnector(const std::string& rx, const std::string& tx, uint32_t baudRate); + TrackPlatform_BasicConnector(); virtual ~TrackPlatform_BasicConnector(); /** diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index d070776..e58664f 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -1,171 +1,173 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {32D3778A-E59E-4DBC-8D86-BD23B708CA12} - Win32Proj - cxxapi - - - - StaticLibrary - true - v141 - Unicode - - - StaticLibrary - false - v141 - true - Unicode - - - StaticLibrary - true - v141 - Unicode - - - StaticLibrary - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - - - - - Level3 - Disabled - _DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - - - - - Level3 - - - MaxSpeed - true - true - NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12} + Win32Proj + cxxapi + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 422dcc7..626015e 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -1,87 +1,93 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {de9cad78-f264-4652-87a0-7f8536f7ef0c} - - - {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} - - - {a897fa9d-d634-41b6-a441-71b4a660fa92} - - - {09716c3b-089b-4880-b137-c4da5ccc81f8} - - - {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} - - - {8cb6d371-6c98-4f8c-ace2-6e3059467355} - - - - - Header Files - - - Header Files - - - serial_support\header - - - serial_support\header - - - serial_support\header - - - Header Files - - - Communication\header - - - Communication\header - - - Communication\header - - - - - Source Files - - - serial_support\source - - - serial_support\source - - - serial_support\source - - - Source Files - - - Communication\source - - - Communication\source - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {de9cad78-f264-4652-87a0-7f8536f7ef0c} + + + {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} + + + {a897fa9d-d634-41b6-a441-71b4a660fa92} + + + {09716c3b-089b-4880-b137-c4da5ccc81f8} + + + {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} + + + {8cb6d371-6c98-4f8c-ace2-6e3059467355} + + + + + Header Files + + + Header Files + + + serial_support\header + + + serial_support\header + + + serial_support\header + + + Header Files + + + Communication\header + + + Communication\header + + + Communication\header + + + Communication\header + + + + + Source Files + + + serial_support\source + + + serial_support\source + + + serial_support\source + + + Source Files + + + Communication\source + + + Communication\source + + + Communication\header + + \ No newline at end of file diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index d4cef88..5118b16 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -3,9 +3,13 @@ #if defined(_WIN32) #include +#else +#include +#define _getche getchar #endif #include "TrackPlatform_Manager.h" +#include "TCPIP_Connector.h" int main(int argc, char* argv[]) { @@ -21,6 +25,8 @@ int main(int argc, char* argv[]) */ std::cout << "rx = " << rx << " tx = " << tx << " baudrate = " << baudrate << std::endl; + TCPIP_Connector tcpip("127.0.0.1", 3333); + try { TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, baudrate); From 32eaf706c5f36bc73205dc5bfb486b6c9925c403 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 10 Aug 2017 16:02:38 +0300 Subject: [PATCH 032/336] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?makefile=20=D0=B4=D0=BB=D1=8F=20linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/makefile | 156 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 code/c++/cxx-api/makefile diff --git a/code/c++/cxx-api/makefile b/code/c++/cxx-api/makefile new file mode 100644 index 0000000..a1141ee --- /dev/null +++ b/code/c++/cxx-api/makefile @@ -0,0 +1,156 @@ +#Make file to compile source code for track platform cxx api library + +#Project Name +PROJECT_NAME = track-platform_cxx-api +#Build option +BUILD ?= BUILD_STATIC +#ANSI Colos +ANSI_COLOR_RED = \e[31m +ANSI_COLOR_GREEN = \e[32m +ANSI_COLOR_YELLOW = \e[33m +ANSI_COLOR_BLUE = \e[34m +ANSI_COLOR_MAGENTA = \e[35m +ANSI_COLOR_CYAN = \e[36m +ANSI_COLOR_RESET = \e[37m +################################Compiller flags############################################################### +#Opitmization Level +OPT_LEVEL = -O0 +#Warning options +WARNINGS = -Wall -Wpedantic #-Werror +# WARNINGS += -fsyntax-only # for syntax checking only, without comlipation +WARNINGS_WITHOUT = +#User Compiller flags +USER_FLAGS ?= +############################################################################################################## +# OS definition +ifndef OS +OS = other +endif + +#Build patch +BUILD_PATH = Output/$(OS) +OBJ_PATH = $(BUILD_PATH)/obj + +#Compiller flags +CFLAGS = $(OPT_LEVEL) +CFLAGS += -g +CFLAGS += $(WARNINGS) +CFLAGS += -I. +CFLAGS += $(USER_FLAGS) +CFLAGS += -std=c++11 +CFLAGS += -D$(BUILD) +# ifeq ($(BUILD), BUILD_STATIC) +# CFLAGS += -D$(BUILD_STATIC) +# endif + +CFLAGS += $(INCLUDES) +############################################################################################################## +#Code file path +SERIAL_PATH = serial_support +SERIAL_SOURCE_PATH = $(SERIAL_PATH)/src +SERIAL_SOURCE_IMPL_PATH = $(SERIAL_SOURCE_PATH)/impl +SERIAL_SOURCE_LIST_PORTS_PATH = $(SERIAL_SOURCE_IMPL_PATH)/list_ports +SERIAL_INCLUDE_PATH = $(SERIAL_PATH)/include +COMMUNICATION_PATH = . +COMMUNICATION_SOURCE_PATH = $(COMMUNICATION_PATH) +COMMUNICATION_INCLUDE_PATH = $(COMMUNICATION_PATH) +OTHER_PATH = . +OTHER_SOURCE_PATH = $(OTHER_PATH) +OTHER_INCLUDE_PATH = $(OTHER_PATH) + +#Linker scrpit file +ARFLAGS = -cvq + +#Source file path + +SOURCES = +# Serial support +SOURCES += $(SERIAL_SOURCE_PATH)/serial.cc +SOURCES += $(SERIAL_SOURCE_IMPL_PATH)/unix.cc +SOURCES += $(SERIAL_SOURCE_LIST_PORTS_PATH)/list_ports_linux.cc +# Communication +SOURCES += $(COMMUNICATION_SOURCE_PATH)/TrackPlatform_BasicConnector.cpp +SOURCES += $(COMMUNICATION_SOURCE_PATH)/SerialConnector.cpp +# Other code (non grouped) +SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_BasicManagement.cpp +SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_Manager.cpp + +#Include file path +INCLUDES = -I$(SERIAL_INCLUDE_PATH) +# INCLUDES += -I$(COMMUNICATION_INCLUDE_PATH) +# INCLUDES += -I$(OTHER_INCLUDE_PATH) + +############################################################################################################## +BUILD_PRINT = $(ANSI_COLOR_GREEN) Building:$(ANSI_COLOR_RESET) $@ +############################################################################################################## +#Output files +STATIC_LIB = $(BUILD_PATH)/$(PROJECT_NAME).a +DYNAMIC_LIB = $(BUILD_PATH)/$(PROJECT_NAME).so + +OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) + +$(STATIC_LIB): $(OBJECTS) + @$(AR) $(ARFLAGS) $@ $(OBJECTS) + @echo -e "$(BUILD_PRINT)" + +$(DYNAMIC_LIB): $(OBJECTS) +# $(error Dynamic library is not supported yet) + @$(CXX) -shared -o $@ $(OBJECTS) + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cc + @mkdir -p $(dir $@) + +ifeq ($(BUILD), BUILD_DYNAMIC) + @$(CXX) -fPIC -c $(CFLAGS) $< -o $@ +else + @$(CXX) -c $(CFLAGS) $< -o $@ +endif + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cpp + @mkdir -p $(dir $@) + +ifeq ($(BUILD), BUILD_DYNAMIC) + @$(CXX) -fPIC -c $(CFLAGS) $< -o $@ +else + @$(CXX) -c $(CFLAGS) $< -o $@ +endif + @echo -e "$(BUILD_PRINT)" + +#Makefile parameters +.DEFAULT_GOAL := all + +all: build + +ifeq ($(BUILD), BUILD_STATIC) +build: $(STATIC_LIB) + +else +ifeq ($(BUILD), BUILD_DYNAMIC) +build: $(DYNAMIC_LIB) + +else +build: + @echo "That BUILD variable is not supported. Use `make help` to see supported variants of build variable" +endif +endif + +dynamic: + $(MAKE) BUILD=BUILD_DYNAMIC + +static: + $(MAKE) BUILD=BUILD_STATIC + +clean: + @rm -rf $(BUILD_PATH) + +set_def_color: + @echo -e "$(ANSI_COLOR_RESET)" + +help: + @echo "$(NEW_LINE)" + @echo "\tall : Builds static or dynamic library (static by default)" + @echo "\t\tIf you want to build static library(.a file), write `make` or `make static` or `make BUILD=BUILD_DYNAMIC`" + @echo "\t\tIf you want to build dynamic library(.so file), write `make dynamic` or `make BUILD=BUILD_DYNAMIC`" + @echo "$(NEW_LINE)" From 447884f997f12cc388c209d8ea62ff840402a714 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 10 Aug 2017 16:45:08 +0300 Subject: [PATCH 033/336] =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B2=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=B2=D0=BE=D0=B4=20=D0=B2=D0=B5=D0=B4=D0=B5=D1=82?= =?UTF-8?q?=20=D1=81=D0=B5=D0=B1=D1=8F=20=D1=81=D1=82=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/trackPlatform.ino | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 1c67301..d70e7e2 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -23,6 +23,7 @@ WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); USB usb; ConnectingDevice *device = nullptr; CommandsController controller; +ServoController* servo; bool connected = false; @@ -36,6 +37,8 @@ void setup() DEBUG_PRINTLN("Arduino was started"); + servo = new ServoController(); + while (!connected) { if (bluetooth.isActive()) { connected = true; @@ -53,6 +56,11 @@ void setup() DEBUG_PRINTLN("USB"); } } + + servo->setHorizontalAndVerticalAngle(90, 90); + delay(1000); + servo->setHorizontalAndVerticalAngle(180, 0); + delay(1000); } void loop() @@ -68,6 +76,11 @@ void loop() controller.handle(device, command); } delay(100); //for sending commands from mobile (not required) + + servo->setHorizontalAndVerticalAngle(0, 180); + delay(1000); + servo->setHorizontalAndVerticalAngle(180, 0); + delay(1000); } #ifdef DIOD_DEBUG From 77dc63174cfff924b6161d24d91ad68e169ac945 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 11 Aug 2017 13:16:28 +0300 Subject: [PATCH 034/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D1=8B=20=D1=81=D0=B5=D1=80=D0=B2=D0=BE=D0=BF=D1=80=D0=B8=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=D0=B0=20=D0=B8=20USB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Сервоприводы работают корректно. Могут наблюдаться небольшие дребезжания позиции сервопривода при использования отладнчной консоли или обмена сообщениями * Для USB убрана илшняя инициализация последовательного порта. Добавлена защита от переинициализации --- code/Arduino/connectors/USB.cpp | 11 +++++-- code/Arduino/connectors/USB.h | 10 +++++- code/Arduino/peripheral/ServoController.cpp | 4 +++ code/Arduino/peripheral/ServoController.h | 5 +++ code/Arduino/trackPlatform.ino | 36 ++++++++------------- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/code/Arduino/connectors/USB.cpp b/code/Arduino/connectors/USB.cpp index dd9ca8f..beb312a 100644 --- a/code/Arduino/connectors/USB.cpp +++ b/code/Arduino/connectors/USB.cpp @@ -1,6 +1,13 @@ -#include "USB.h" +#include "../Constants.h" +#include "USB.h" + +bool USB::isInited = false; USB::USB() : ConnectingDevice(&Serial) { - //TODO: start serial on speed Constants::usb_serial_speed in `setup` loop + if (!isInited) + { + isInited = true; + Serial.begin(Constants::usb_serial_speed); + } } diff --git a/code/Arduino/connectors/USB.h b/code/Arduino/connectors/USB.h index 2521bc4..7c124ce 100644 --- a/code/Arduino/connectors/USB.h +++ b/code/Arduino/connectors/USB.h @@ -1,10 +1,18 @@ #pragma once -#include #include "ConnectingDevice.h" +/** + * @brief USB controller class + * @attention Create first object of that class in setup() method only + */ class USB : public ConnectingDevice { + /** + * @brief Block for double initialization + */ + static bool isInited; + public: USB(); }; diff --git a/code/Arduino/peripheral/ServoController.cpp b/code/Arduino/peripheral/ServoController.cpp index 7639f50..aad96f3 100644 --- a/code/Arduino/peripheral/ServoController.cpp +++ b/code/Arduino/peripheral/ServoController.cpp @@ -1,5 +1,6 @@ #include "../CommandsEnum.h" #include "../connectors/ConnectingDevice.h" +#include "../connectors/DebugSerial.h" #include "ServoController.h" ServoController::ServoController() @@ -45,11 +46,13 @@ void ServoController::setHorizontalAngle(int angle) { } void ServoController::setVerticalAngle(int angle) { + DEBUG_PRINTF("Set vertical (%d) angle\n", angle); verticalServo.write(angle); delay(constants.servo_delay); } void ServoController::setHorizontalAndVerticalAngle(int angleX, int angleY) { + DEBUG_PRINTF("Set horisontal (%d) and vertical (%d) angles\n", angleX, angleY); horizontalServo.write(angleX); verticalServo.write(angleY); delay(constants.servo_delay); @@ -63,6 +66,7 @@ int* ServoController::getCoordinates() { } void ServoController::setHorizontalAndVerticalAngle(int* arr) { + DEBUG_PRINTF("Set horisontal (%d) and vertical (%d) angles\n", arr[0], arr[1]); horizontalServo.write(arr[0]); verticalServo.write(arr[1]); delay(constants.servo_delay); diff --git a/code/Arduino/peripheral/ServoController.h b/code/Arduino/peripheral/ServoController.h index 5834ee7..85f621b 100644 --- a/code/Arduino/peripheral/ServoController.h +++ b/code/Arduino/peripheral/ServoController.h @@ -2,6 +2,10 @@ #include #include "MainController.h" +/** + * @brief Servo controller for 2 axes: X & Y + * @attention Turn off debug console to correct working + */ class ServoController : public MainController { Servo horizontalServo; @@ -11,6 +15,7 @@ class ServoController : public MainController public: ServoController(); + void exec(ConnectingDevice*, String); void setHorizontalAngle(int angle); void setVerticalAngle(int angle); diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index d70e7e2..2489cda 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -20,12 +20,9 @@ void off45(); Constants constants; Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bluetooth_serial_speed); WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); -USB usb; +USB* usb; ConnectingDevice *device = nullptr; -CommandsController controller; -ServoController* servo; - -bool connected = false; +CommandsController* controller; void setup() { @@ -33,12 +30,12 @@ void setup() diodInit(); #endif /* DIOD_DEBUG */ - Serial.begin(Constants::usb_serial_speed); - DEBUG_PRINTLN("Arduino was started"); - servo = new ServoController(); + usb = new USB(); + controller = new CommandsController(); + bool connected = false; while (!connected) { if (bluetooth.isActive()) { connected = true; @@ -50,37 +47,30 @@ void setup() device = &wifi; DEBUG_PRINTLN("Wifi"); } - else if (usb.isActive()) { + else if (usb->isActive()) { connected = true; - device = &usb; + device = usb; DEBUG_PRINTLN("USB"); } } - - servo->setHorizontalAndVerticalAngle(90, 90); - delay(1000); - servo->setHorizontalAndVerticalAngle(180, 0); - delay(1000); } void loop() { while (device->isActive()) + //while(true) { String command = device->read(); + //String command = "\x03\x02""45"; - //debug + //debug DEBUG_PRINT("Command: "); DEBUG_PRINTLNHEX(command); - controller.handle(device, command); + controller->handle(device, command); + //controller->handle(device, "0"); } - delay(100); //for sending commands from mobile (not required) - - servo->setHorizontalAndVerticalAngle(0, 180); - delay(1000); - servo->setHorizontalAndVerticalAngle(180, 0); - delay(1000); + delay(1); //for sending commands from mobile (not required) } #ifdef DIOD_DEBUG From cf68dc5848951265e11b90baeff80fe7a272b5ab Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 11 Aug 2017 13:28:32 +0300 Subject: [PATCH 035/336] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Исправлены методы MainController::parse_command() и MainController::intArrayToString() * Убраны лишние комментарии --- code/Arduino/peripheral/MainController.cpp | 19 +++++++++++-------- code/Arduino/trackPlatform.ino | 3 --- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/Arduino/peripheral/MainController.cpp b/code/Arduino/peripheral/MainController.cpp index 1988ff9..6df8a35 100644 --- a/code/Arduino/peripheral/MainController.cpp +++ b/code/Arduino/peripheral/MainController.cpp @@ -7,14 +7,13 @@ MainController::MainController() { int* MainController::parse_command(String command, int begin, char delimetr, int paramsLength) { int* arr = new int[paramsLength]; - for (int i = 0; i < paramsLength; i++) { - int delimetrPos = command.indexOf(delimetr); - if (delimetrPos >= 0) { - arr[i] = command.substring(begin, delimetrPos).toInt(); - begin = delimetrPos + 1; - command = command.substring(begin, command.length()); - begin = 0; - } + command = command.substring(begin); + int delimetrPos = command.indexOf(delimetr); + for (int i = 0; (i < paramsLength) && (delimetrPos >= 0); i++) { + arr[i] = command.substring(begin, delimetrPos).toInt(); + command = command.substring(delimetrPos + 1); + begin = 0; + delimetrPos = command.indexOf(delimetr); } return arr; } @@ -30,6 +29,10 @@ String MainController::intArrayToString(int* array, int size) { str += String(array[i]); str += constants.commands_delimetr; } + if (size > 0) + { + str = str.substring(0, str.length() - 1); + } return str; } diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 2489cda..d3eabf3 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -58,17 +58,14 @@ void setup() void loop() { while (device->isActive()) - //while(true) { String command = device->read(); - //String command = "\x03\x02""45"; //debug DEBUG_PRINT("Command: "); DEBUG_PRINTLNHEX(command); controller->handle(device, command); - //controller->handle(device, "0"); } delay(1); //for sending commands from mobile (not required) } From 4a03c14feef2a8ef7ab2c5c0695db3810687730c Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 11 Aug 2017 13:32:29 +0300 Subject: [PATCH 036/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=BE=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=20=D1=81=D0=B5=D1=80=D0=B2?= =?UTF-8?q?=D0=BE=D0=BF=D1=80=D0=B8=D0=B2=D0=BE=D0=B4=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/main.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index d4cef88..6d78741 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -45,6 +45,8 @@ int main(int argc, char* argv[]) std::cout << "e: get fixed line value" << std::endl; std::cout << "t: get all distance values" << std::endl; std::cout << "y: get fixed distance value" << std::endl; + std::cout << "g: set horisontal servo angle in degree" << std::endl; + std::cout << "h: set vertical servo angle in degree" << std::endl; break; case 'q': isExit = true; @@ -98,6 +100,22 @@ int main(int argc, char* argv[]) std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a) << std::endl; break; } + case 'g': + { + std::cout << "Input num: "; + int a; + std::cin >> a; + trackPlatform.servoSetHorizontalAngle(a); + break; + } + case 'h': + { + std::cout << "Input num: "; + int a; + std::cin >> a; + trackPlatform.servoSetVerticalAngle(a); + break; + } default: break; } } From c11a5cb22416bfe1930d2a539d73e6b4d6113d24 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 11 Aug 2017 13:38:08 +0300 Subject: [PATCH 037/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=BA=D0=BE=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=D0=B8=20=D0=BF=D1=80=D0=B5=D0=B4=D1=83=D0=BF=D1=80=D0=B5?= =?UTF-8?q?=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/CommandsController.h | 4 ++++ code/Arduino/peripheral/ServoController.h | 1 + 2 files changed, 5 insertions(+) diff --git a/code/Arduino/CommandsController.h b/code/Arduino/CommandsController.h index d21ea74..40a8a39 100644 --- a/code/Arduino/CommandsController.h +++ b/code/Arduino/CommandsController.h @@ -6,6 +6,10 @@ #include "peripheral/ServoController.h" #include "connectors/ConnectingDevice.h" +/** + * @brief Peripheral manager class (parse commands and sends it) + * @attention Create only one object of that class. And create it in setup() method only + */ class CommandsController { MovementController moveController; diff --git a/code/Arduino/peripheral/ServoController.h b/code/Arduino/peripheral/ServoController.h index 85f621b..8a70bf6 100644 --- a/code/Arduino/peripheral/ServoController.h +++ b/code/Arduino/peripheral/ServoController.h @@ -5,6 +5,7 @@ /** * @brief Servo controller for 2 axes: X & Y * @attention Turn off debug console to correct working + * @attention Create only one object of that class. And create it in setup() method only */ class ServoController : public MainController { From a596407d34ed1f27144b97f13ca74843b00a9058 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Fri, 11 Aug 2017 20:58:15 +0300 Subject: [PATCH 038/336] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=20=D1=87=D0=B0=D1=81=D1=82=D0=B8=D1=87=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 102 ++++++++++++++++++++++++++++++- code/Arduino/connectors/WiFi.h | 76 ++++++++++++++++++++++- 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index d01bebb..cb7b4ae 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -4,9 +4,109 @@ WiFi::WiFi(int rx, int tx, int speed) : ConnectingDevice(rx, tx, speed) { + Check(); + ChangeSpeed(speed); } - WiFi::~WiFi() { } + +String WiFi::VersionCheck() +{ + send("AT+GMR"); + return read(); +} + +String CheckIPandMAC() +{ + send("AT+CIFSR"); + return read(); +} + +void WiFi::ChangeSpeed(int speed) +{ + if (ready) + { + send("AT+CIOBAUD=" + speed); + } +} + +void WiFi::Reset(int speed) +{ + send("AT+RST"); + Check(); + ChangeSpeed(speed); +} + +void WiFi::CurrentLog(String name, String password, int port) +{ + if (ready) + { + if (!opened) + { + Open(); + } + send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); + UseTCP(port); + } +} + +void WiFi::StaticLog(String name, String password, int port) +{ + if (ready) + { + if (!opened) + { + Open(); + } + send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); + UseTCP(port); + } +} + +String WiFi::NetsList() +{ + if (ready) + { + if (opened) + { + Close(); + } + send("AT+CWLAP"); + return read(); + } +} + +void WiFi::Close() +{ + send("AT+CWMODE_CUR=1"); + opened = false; +} + +void WiFi::Open() +{ + send("AT+CWMODE_CUR=2"); + opened = true; +} + +void WiFi::UseTCP(int port) +{ + send("AT+CIPMUX=1"); + send("AT+CIPSERVER=1," + port); +} + +void WiFi::Check() +{ + send("AT"); + if (read() == "OK") + { + ready = true; + Close(); + } + else + { + ready = false; + } +} + diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 0eb8f5f..75b389b 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -6,5 +6,79 @@ class WiFi : public ConnectingDevice public: WiFi(int rx, int tx, int speed); ~WiFi(); -}; + + /** + * + * String + */ + virtual String VersionCheck(); + + /** + * + * String + */ + virtual String NetsList(); + + /** + * IP MAC + * String + */ + virtual String CheckIPandMAC(); + /** + * + * + */ + virtual void ChangeSpeed(int speed); + + /** + * + * + */ + virtual void Reset(int speed); + + /** + * + */ + virtual void Check(); + + /** + * + */ + virtual void Close(); + + /** + * TCP + */ + virtual void Open(); + + /** + * TCP + * int + */ + virtual void UseTCP(int port); + + /** + * + * String, String int UseTCP + */ + virtual void CurrentLog(String name, String password, int port); + + /** + * + * String, String int UseTCP + */ + virtual void StaticLog(String name, String password, int port); + +private: + + /** + * + */ + bool ready = false; + + /** + * / + */ + bool opened = false; +}; \ No newline at end of file From 33a35a0e41a08dab2d3c705bb32a1a426a28545b Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 14 Aug 2017 00:11:41 +0300 Subject: [PATCH 039/336] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D0=BF=D0=BE=20WinAPI=20TCP/IP=20&=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=D0=BC=20=D0=B2=20=D0=BE=D0=B1=D1=89=D0=B5=D0=BC=20?= =?UTF-8?q?*=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=B0=20=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20*=20TCP/IP=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D1=87=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20=D0=BF=D0=BB=D0=B0=D1=84=D0=BE=D1=80=D0=BC=D0=BE=D0=B7?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC=D0=B0=D1=8F=20*=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20=D1=83=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D1=81?= =?UTF-8?q?=D0=B1=D1=80=D0=BE=D1=81=D0=B0=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0=20=D1=83=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BD=D0=B5=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84?= =?UTF-8?q?=D0=B5=D0=B9=D1=81=D0=B0=20*=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=20TCP/IP=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=8F=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20IP?= =?UTF-8?q?=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=D0=B0=20(=D0=B1=D0=B5=D0=B7?= =?UTF-8?q?=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8-=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=B5=D0=BC=D0=B0=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B9)=20*=20=D0=9F=D0=BE=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B7=D0=B0=D1=89=D0=B8=D1=82?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=BF=D1=8B=D1=82=D0=BA?= =?UTF-8?q?=D1=83=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20win32=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B4=D1=80=D1=83=D0=B3=D0=BE=D0=B9=20=D0=BF=D0=BB?= =?UTF-8?q?=D0=B0=D1=82=D1=84=D0=BE=D1=80=D0=BC=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/BadAddressOrPortException.h | 14 ++ code/c++/cxx-api/SerialConnector.cpp | 25 ++++ code/c++/cxx-api/SerialConnector.h | 2 + code/c++/cxx-api/SocketException.h | 10 ++ code/c++/cxx-api/SocketShutdownException.h | 11 ++ code/c++/cxx-api/TCPIP_Connector.cpp | 90 ------------- code/c++/cxx-api/TCPIP_Connector.h | 20 --- code/c++/cxx-api/TrackPlatformException.cpp | 10 ++ code/c++/cxx-api/TrackPlatformException.h | 14 ++ .../cxx-api/TrackPlatform_BasicConnector.h | 8 ++ code/c++/cxx-api/WSAStartupException.h | 14 ++ code/c++/cxx-api/cxx-api.vcxproj | 18 ++- code/c++/cxx-api/cxx-api.vcxproj.filters | 33 ++++- .../windows/TCPIP_Connector.cpp | 120 ++++++++++++++++++ .../windows/TCPIP_Connector.h | 59 +++++++++ code/c++/cxx-app/main.cpp | 2 +- 16 files changed, 330 insertions(+), 120 deletions(-) create mode 100644 code/c++/cxx-api/BadAddressOrPortException.h create mode 100644 code/c++/cxx-api/SocketException.h create mode 100644 code/c++/cxx-api/SocketShutdownException.h delete mode 100644 code/c++/cxx-api/TCPIP_Connector.cpp delete mode 100644 code/c++/cxx-api/TCPIP_Connector.h create mode 100644 code/c++/cxx-api/TrackPlatformException.cpp create mode 100644 code/c++/cxx-api/TrackPlatformException.h create mode 100644 code/c++/cxx-api/WSAStartupException.h create mode 100644 code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp create mode 100644 code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h diff --git a/code/c++/cxx-api/BadAddressOrPortException.h b/code/c++/cxx-api/BadAddressOrPortException.h new file mode 100644 index 0000000..9bc8745 --- /dev/null +++ b/code/c++/cxx-api/BadAddressOrPortException.h @@ -0,0 +1,14 @@ +#ifndef _BAD_ADDRESS_OR_PORT_EXCEPTION_H_ +#define _BAD_ADDRESS_OR_PORT_EXCEPTION_H_ + +#include "TrackPlatformException.h" + +class BadAddressOrPortException : public TrackPlatformException +{ +public: + explicit BadAddressOrPortException(int errorCode) : TrackPlatformException(std::to_string(errorCode)) + { + } +}; + +#endif /* _BAD_ADDRESS_OR_PORT_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index cbd4e9a..a701c52 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -13,6 +13,7 @@ SerialConnector::SerialConnector(const std::string& rx, const std::string& tx, u SerialConnector::~SerialConnector() { + SerialConnector::disconnect(); if (readPort != writePort) { delete writePort; @@ -34,3 +35,27 @@ std::string SerialConnector::readOneAnswer() { return readPort->readline(messageMaxSize, std::string(1, stopSymbol)); } + +void SerialConnector::connect() +{ + if (readPort && !readPort->isOpen()) + { + readPort->open(); + } + if (writePort && !writePort->isOpen()) + { + writePort->open(); + } +} + +void SerialConnector::disconnect() +{ + if (readPort && readPort->isOpen()) + { + readPort->close(); + } + if (writePort && writePort->isOpen()) + { + writePort->close(); + } +} diff --git a/code/c++/cxx-api/SerialConnector.h b/code/c++/cxx-api/SerialConnector.h index a1255c5..a699bcd 100644 --- a/code/c++/cxx-api/SerialConnector.h +++ b/code/c++/cxx-api/SerialConnector.h @@ -25,6 +25,8 @@ class SerialConnector : public TrackPlatform_BasicConnector ~SerialConnector() override; bool isConnected() override; std::string readOneAnswer() override; + void connect() override; + void disconnect() override; }; #endif /* _BLUETOOTH_CONNECTOR_H_ */ diff --git a/code/c++/cxx-api/SocketException.h b/code/c++/cxx-api/SocketException.h new file mode 100644 index 0000000..9c8c55f --- /dev/null +++ b/code/c++/cxx-api/SocketException.h @@ -0,0 +1,10 @@ +#pragma once +#include "TrackPlatformException.h" + +class SocketException : public TrackPlatformException +{ +public: + explicit SocketException(int errorCode) : TrackPlatformException(std::to_string(errorCode)) + { + } +}; diff --git a/code/c++/cxx-api/SocketShutdownException.h b/code/c++/cxx-api/SocketShutdownException.h new file mode 100644 index 0000000..fc3608b --- /dev/null +++ b/code/c++/cxx-api/SocketShutdownException.h @@ -0,0 +1,11 @@ +#pragma once +#include "SocketException.h" + +class SocketShutdownException : public SocketException +{ +public: + explicit SocketShutdownException(int errorCode) + : SocketException(errorCode) + { + } +}; diff --git a/code/c++/cxx-api/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp deleted file mode 100644 index 94bae54..0000000 --- a/code/c++/cxx-api/TCPIP_Connector.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifdef _WIN32 - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include -#include -#include -#include - -#pragma comment(lib, "Ws2_32.lib") - -#endif - -#include "TCPIP_Connector.h" - -void TCPIP_Connector::write(const std::string& s) -{ - //TODO -} - -std::string TCPIP_Connector::read() -{ - //TODO - return std::string(); -} - -bool TCPIP_Connector::isConnected() -{ - //TODO - return false; -} - -TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) - : ip(ip), port(port) -{ - //TODO - -#ifdef _WIN32 - WSADATA wsaData; - - // Initialize Winsock - int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) { - printf("WSAStartup failed: %d\n", iResult); - return; - //TODO: throw exception - } - - - struct addrinfo *result = NULL, - *ptr = NULL, - hints; - - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - -#define DEFAULT_PORT "27015" - - // Resolve the server address and port - iResult = getaddrinfo(ip.c_str(), DEFAULT_PORT, &hints, &result); - if (iResult != 0) { - printf("getaddrinfo failed: %d\n", iResult); - WSACleanup(); - return; - } - - SOCKET ConnectSocket = INVALID_SOCKET; - - // Attempt to connect to the first address returned by - // the call to getaddrinfo - ptr = result; - - // Create a SOCKET for connecting to server - ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, - ptr->ai_protocol); - - if (ConnectSocket == INVALID_SOCKET) { - printf("Error at socket(): %ld\n", WSAGetLastError()); - freeaddrinfo(result); - WSACleanup(); - return; - } - -#endif - -} diff --git a/code/c++/cxx-api/TCPIP_Connector.h b/code/c++/cxx-api/TCPIP_Connector.h deleted file mode 100644 index a434783..0000000 --- a/code/c++/cxx-api/TCPIP_Connector.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _TCPIP_CONNECTOR_H_ -#define _TCPIP_CONNECTOR_H_ - -#include "TrackPlatform_BasicConnector.h" - -class TCPIP_Connector : public TrackPlatform_BasicConnector -{ - std::string ip; - uint16_t port; - -protected: - void write(const std::string& s) override; - std::string read() override; -public: - TCPIP_Connector(const std::string& ip, uint16_t port); - - bool isConnected() override; -}; - -#endif diff --git a/code/c++/cxx-api/TrackPlatformException.cpp b/code/c++/cxx-api/TrackPlatformException.cpp new file mode 100644 index 0000000..d2af835 --- /dev/null +++ b/code/c++/cxx-api/TrackPlatformException.cpp @@ -0,0 +1,10 @@ +#include "TrackPlatformException.h" + +TrackPlatformException::TrackPlatformException() +{ +} + +TrackPlatformException::TrackPlatformException(const std::string& errorMessage) + : std::exception(errorMessage.c_str()) +{ +} diff --git a/code/c++/cxx-api/TrackPlatformException.h b/code/c++/cxx-api/TrackPlatformException.h new file mode 100644 index 0000000..93ccb98 --- /dev/null +++ b/code/c++/cxx-api/TrackPlatformException.h @@ -0,0 +1,14 @@ +#ifndef _TRACK_PLATFORM_EXCEPTION_H_ +#define _TRACK_PLATFORM_EXCEPTION_H_ + +#include +#include + +class TrackPlatformException : public std::exception +{ +public: + TrackPlatformException(); + explicit TrackPlatformException(const std::string& errorMessage); +}; + +#endif /* _TRACK_PLATFORM_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index 273ba14..fbe7c8d 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -22,6 +22,14 @@ class TrackPlatform_BasicConnector virtual std::string readOneAnswer(); virtual void sendOneCommand(const std::string& s); virtual bool isConnected() = 0; + /** + * @brief Manual connect if not already connected + */ + virtual void connect() = 0; + /** + * @brief Manual disconnect + */ + virtual void disconnect() = 0; }; #endif /* _TRACKPLATFORM_BASICCONNECTOR_H_ */ diff --git a/code/c++/cxx-api/WSAStartupException.h b/code/c++/cxx-api/WSAStartupException.h new file mode 100644 index 0000000..3f108c4 --- /dev/null +++ b/code/c++/cxx-api/WSAStartupException.h @@ -0,0 +1,14 @@ +#ifndef _WSA_STARTUP_EXCEPTION_H_ +#define _WSA_STARTUP_EXCEPTION_H_ + +#include "TrackPlatformException.h" + +class WSAStartupException : public TrackPlatformException +{ +public: + explicit WSAStartupException(int errorCode) : TrackPlatformException(std::to_string(errorCode)) + { + } +}; + +#endif /* _WSA_STARTUP_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index e58664f..8d9bb0c 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -70,22 +70,22 @@ - $(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - $(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - $(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - $(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ @@ -146,23 +146,29 @@ + + - + + + + + - + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 626015e..42dda6b 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -31,6 +31,15 @@ {8cb6d371-6c98-4f8c-ace2-6e3059467355} + + {c8707437-f967-4f30-b1b5-cde6082dca67} + + + {20cccc26-6e34-4b3e-8ed5-4d44cbf4c28e} + + + {42cc74a7-2d02-4a96-828e-2b504625d84d} + @@ -60,7 +69,22 @@ Communication\header - + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + Communication\header @@ -86,8 +110,11 @@ Communication\source - - Communication\header + + exceptions\source + + + Communication\source \ No newline at end of file diff --git a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp new file mode 100644 index 0000000..36a6a6d --- /dev/null +++ b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp @@ -0,0 +1,120 @@ +#ifndef _WIN32 + +#error This source file must be used only on Windows desktop platforms (win32) + +#else /* _WIN32 */ + +#include "WSAStartupException.h" +#include "BadAddressOrPortException.h" +#include "SocketException.h" +#include "SocketShutdownException.h" +#include "TCPIP_Connector.h" + +void TCPIP_Connector::write(const std::string& s) +{ + //TODO +} + +std::string TCPIP_Connector::read() +{ + //TODO + return std::string(); +} + +void TCPIP_Connector::closeSocket() +{ + if (connectedSocket != INVALID_SOCKET) + { + closesocket(connectedSocket); + connectedSocket = INVALID_SOCKET; + } +} + +bool TCPIP_Connector::isConnected() +{ + return isConnected_private; +} + +void TCPIP_Connector::connect() +{ + if (isConnected_private) { + return; + } + + struct addrinfo *ptr = nullptr, hints; + + // Configure socket + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* AF_UNSPEC for IPv6 or IPv4 (automatically); AF_INET6 for IPv6; AF_INET for IPv4 */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + // Resolve the server address and port + int iResult = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &addressInfo); + if (iResult != 0) { + addressInfo = nullptr; + throw BadAddressOrPortException(iResult); + } + + // Attempt to connect to the first address returned by + // the call to getaddrinfo + ptr = addressInfo; + + // Create a SOCKET for connecting to server + connectedSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + + if (connectedSocket == INVALID_SOCKET) { + throw SocketException(WSAGetLastError()); + } + + // Connect to server. + iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); + if (iResult == SOCKET_ERROR) { + closeSocket(); + } + else + { + isConnected_private = true; + } +} + +void TCPIP_Connector::disconnect() +{ + if (!isConnected_private) + { + return; + } + + // shutdown the sending and recieving data by socket + int iResult = shutdown(connectedSocket, SD_BOTH); + if (iResult == SOCKET_ERROR) { + throw SocketShutdownException(WSAGetLastError()); + } + + closeSocket(); + isConnected_private = false; +} + +TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) + : ip(ip), port(port) +{ + // Initialize Winsock + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != 0) { + throw WSAStartupException(iResult); + } + + TCPIP_Connector::connect(); +} + +TCPIP_Connector::~TCPIP_Connector() +{ + TCPIP_Connector::disconnect(); + if (addressInfo) + { + freeaddrinfo(addressInfo); + } + WSACleanup(); +} + +#endif /* _WIN32 */ diff --git a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h new file mode 100644 index 0000000..d148017 --- /dev/null +++ b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h @@ -0,0 +1,59 @@ +#ifndef _TCPIP_CONNECTOR_H_ +#define _TCPIP_CONNECTOR_H_ + +#ifndef _WIN32 + +#error This header file must be used only on Windows desktop platforms (win32) + +#else /* _WIN32 */ + +/* WinAPI include */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") + +#include "TrackPlatform_BasicConnector.h" + +class TCPIP_Connector : public TrackPlatform_BasicConnector +{ + std::string ip; + uint16_t port; + + WSADATA wsaData; + struct addrinfo *addressInfo = nullptr; + SOCKET connectedSocket = INVALID_SOCKET; + + bool isConnected_private = false; + + void closeSocket(); + +protected: + void write(const std::string& s) override; + std::string read() override; + +public: + /** + * @brief Create TCP/IP connector to trackPlatform + * @warning Only one object of that class in one moment of time is supported + * + * @param ip IP of trackPlatform Wi-Fi module + * @warning Supports only single IP, no masks + * @param port Port of TCP/IP server on trackPlatform + */ + TCPIP_Connector(const std::string& ip, uint16_t port); + virtual ~TCPIP_Connector(); + + bool isConnected() override; + void connect() override; + void disconnect() override; +}; + +#endif /* _WIN32 */ +#endif /* _TCPIP_CONNECTOR_H_ */ diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 5118b16..0ecfb20 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -9,7 +9,7 @@ #endif #include "TrackPlatform_Manager.h" -#include "TCPIP_Connector.h" +#include "platform-dependent/windows/TCPIP_Connector.h" int main(int argc, char* argv[]) { From 9b899326548109c6661f8243451ba6025dcea07b Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 14 Aug 2017 11:07:15 +0300 Subject: [PATCH 040/336] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D0=BF=D0=BE=20TCP/IP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Реализованы функции приема/отправки сообщений без блокировки API, если для принятия ничего не ожидается * Защита от вторичного включения всех исключений переделана в gcc-стиле --- code/c++/cxx-api/SocketException.h | 5 +- code/c++/cxx-api/SocketReceiveException.h | 14 ++++ code/c++/cxx-api/SocketSendException.h | 14 ++++ code/c++/cxx-api/SocketShutdownException.h | 5 +- code/c++/cxx-api/cxx-api.vcxproj | 3 + code/c++/cxx-api/cxx-api.vcxproj.filters | 9 +++ .../windows/TCPIP_Connector.cpp | 81 +++++++++++++------ .../windows/TCPIP_Connector.h | 4 + code/c++/cxx-api/trackPlatformAllExceptions.h | 12 +++ 9 files changed, 121 insertions(+), 26 deletions(-) create mode 100644 code/c++/cxx-api/SocketReceiveException.h create mode 100644 code/c++/cxx-api/SocketSendException.h create mode 100644 code/c++/cxx-api/trackPlatformAllExceptions.h diff --git a/code/c++/cxx-api/SocketException.h b/code/c++/cxx-api/SocketException.h index 9c8c55f..211e00b 100644 --- a/code/c++/cxx-api/SocketException.h +++ b/code/c++/cxx-api/SocketException.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef _SOCKET_EXCEPTION_H_ +#define _SOCKET_EXCEPTION_H_ #include "TrackPlatformException.h" class SocketException : public TrackPlatformException @@ -8,3 +9,5 @@ class SocketException : public TrackPlatformException { } }; + +#endif /* _SOCKET_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/SocketReceiveException.h b/code/c++/cxx-api/SocketReceiveException.h new file mode 100644 index 0000000..b614c29 --- /dev/null +++ b/code/c++/cxx-api/SocketReceiveException.h @@ -0,0 +1,14 @@ +#ifndef _SOCKET_RECEIVE_EXCEPTION_H_ +#define _SOCKET_RECEIVE_EXCEPTION_H_ +#include "SocketException.h" + +class SocketReceiveException : public SocketException +{ +public: + explicit SocketReceiveException(int errorCode) + : SocketException(errorCode) + { + } +}; + +#endif /* _SOCKET_RECEIVE_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/SocketSendException.h b/code/c++/cxx-api/SocketSendException.h new file mode 100644 index 0000000..4fd55a8 --- /dev/null +++ b/code/c++/cxx-api/SocketSendException.h @@ -0,0 +1,14 @@ +#ifndef _SOCKET_SEND_EXCETION_H_ +#define _SOCKET_SEND_EXCETION_H_ +#include "SocketException.h" + +class SocketSendException : public SocketException +{ +public: + explicit SocketSendException(int errorCode) + : SocketException(errorCode) + { + } +}; + +#endif /* _SOCKET_SEND_EXCETION_H_ */ diff --git a/code/c++/cxx-api/SocketShutdownException.h b/code/c++/cxx-api/SocketShutdownException.h index fc3608b..67ee430 100644 --- a/code/c++/cxx-api/SocketShutdownException.h +++ b/code/c++/cxx-api/SocketShutdownException.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef _SOCKET_SHUTDOWN_EXCEPTION_H_ +#define _SOCKET_SHUTDOWN_EXCEPTION_H_ #include "SocketException.h" class SocketShutdownException : public SocketException @@ -9,3 +10,5 @@ class SocketShutdownException : public SocketException { } }; + +#endif /* _SOCKET_SHUTDOWN_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 8d9bb0c..f6fb778 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -155,7 +155,10 @@ + + + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 42dda6b..ccaafa5 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -87,6 +87,15 @@ Communication\header + + exceptions\header + + + exceptions + + + exceptions\header + diff --git a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp index 36a6a6d..8b68869 100644 --- a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp @@ -4,21 +4,68 @@ #else /* _WIN32 */ -#include "WSAStartupException.h" -#include "BadAddressOrPortException.h" -#include "SocketException.h" -#include "SocketShutdownException.h" +#include "trackPlatformAllExceptions.h" #include "TCPIP_Connector.h" void TCPIP_Connector::write(const std::string& s) { - //TODO + // Send an initial buffer (returns byte sended) + int iResult = send(connectedSocket, s.c_str(), static_cast(s.length()), 0); + if (iResult == SOCKET_ERROR) { + throw SocketSendException(WSAGetLastError()); + } } std::string TCPIP_Connector::read() { - //TODO - return std::string(); + std::string answer; + char recvbuf[onePacketMaxSize]; + + int iResult; + + do { + // Check if something is already in buffer (and wait `microsecondsToWaitAnswer` if required) + timeval tval = { 0, microsecondsToWaitAnswer }; + fd_set readSockets = { 1, { connectedSocket } }; + iResult = select(NULL, &readSockets, NULL, NULL, &tval); + if (iResult == SOCKET_ERROR) + { + throw SocketException(WSAGetLastError()); + } + if (iResult > 0) + { + break; + } + + // Receive data until the server closes the connection + iResult = recv(connectedSocket, recvbuf, sizeof(recvbuf), 0); + if (iResult < 0) + { + throw SocketReceiveException(WSAGetLastError()); + } + + answer += std::string(recvbuf, iResult); + } while (iResult > 0); + + return answer; +} + +void TCPIP_Connector::configureSocket() +{ + struct addrinfo hints; + + // Configure socket + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* AF_UNSPEC for IPv6 or IPv4 (automatically); AF_INET6 for IPv6; AF_INET for IPv4 */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + // Resolve the server address and port + int iResult = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &addressInfo); + if (iResult != 0) { + addressInfo = nullptr; + throw BadAddressOrPortException(iResult); + } } void TCPIP_Connector::closeSocket() @@ -41,24 +88,9 @@ void TCPIP_Connector::connect() return; } - struct addrinfo *ptr = nullptr, hints; - - // Configure socket - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* AF_UNSPEC for IPv6 or IPv4 (automatically); AF_INET6 for IPv6; AF_INET for IPv4 */ - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - // Resolve the server address and port - int iResult = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &addressInfo); - if (iResult != 0) { - addressInfo = nullptr; - throw BadAddressOrPortException(iResult); - } - // Attempt to connect to the first address returned by // the call to getaddrinfo - ptr = addressInfo; + struct addrinfo* ptr = addressInfo; // Create a SOCKET for connecting to server connectedSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); @@ -68,7 +100,7 @@ void TCPIP_Connector::connect() } // Connect to server. - iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); + int iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); if (iResult == SOCKET_ERROR) { closeSocket(); } @@ -104,6 +136,7 @@ TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) throw WSAStartupException(iResult); } + configureSocket(); TCPIP_Connector::connect(); } diff --git a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h index d148017..ffdb1ab 100644 --- a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h +++ b/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h @@ -26,12 +26,16 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector std::string ip; uint16_t port; + static const uint16_t onePacketMaxSize = 512; + static const int32_t microsecondsToWaitAnswer = 100000; + WSADATA wsaData; struct addrinfo *addressInfo = nullptr; SOCKET connectedSocket = INVALID_SOCKET; bool isConnected_private = false; + void configureSocket(); void closeSocket(); protected: diff --git a/code/c++/cxx-api/trackPlatformAllExceptions.h b/code/c++/cxx-api/trackPlatformAllExceptions.h new file mode 100644 index 0000000..39ad92a --- /dev/null +++ b/code/c++/cxx-api/trackPlatformAllExceptions.h @@ -0,0 +1,12 @@ +#ifndef _TRACK_PLATFORM_ALL_EXCEPTIONS_H_ +#define _TRACK_PLATFORM_ALL_EXCEPTIONS_H_ + +#include "TrackPlatformException.h" +#include "WSAStartupException.h" +#include "BadAddressOrPortException.h" +#include "SocketException.h" +#include "SocketShutdownException.h" +#include "SocketSendException.h" +#include "SocketReceiveException.h" + +#endif /* _TRACK_PLATFORM_ALL_EXCEPTIONS_H_ */ From 4423af6a69831795c71a1388c400a3e8c72a2906 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 14 Aug 2017 12:23:40 +0300 Subject: [PATCH 041/336] =?UTF-8?q?*=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20makefile=20=D0=B4=D0=BB=D1=8F=20cxx-app=20?= =?UTF-8?q?(=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D0=B0).=20=D0=9F=D0=BE?= =?UTF-8?q?=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20=D1=82=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=BA=D0=BE=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B9=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE?= =?UTF-8?q?=D1=82=D0=B5=D0=BA=D0=B8=20*=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8?= =?UTF-8?q?=D0=BB=D1=8F=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=B4=20linux=20(?= =?UTF-8?q?=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=5Fgetche=20=D0=BD=D0=B0=20gerchar)=20*=20?= =?UTF-8?q?=D0=9E=D1=82=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=20=D1=84=D0=BB?= =?UTF-8?q?=D0=B0=D0=B3=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BE=D1=87=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/makefile | 5 +- code/c++/cxx-app/main.cpp | 3 + code/c++/cxx-app/makefile | 150 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 code/c++/cxx-app/makefile diff --git a/code/c++/cxx-api/makefile b/code/c++/cxx-api/makefile index a1141ee..8bc9b5d 100644 --- a/code/c++/cxx-api/makefile +++ b/code/c++/cxx-api/makefile @@ -33,7 +33,7 @@ OBJ_PATH = $(BUILD_PATH)/obj #Compiller flags CFLAGS = $(OPT_LEVEL) -CFLAGS += -g +CFLAGS += -g0 CFLAGS += $(WARNINGS) CFLAGS += -I. CFLAGS += $(USER_FLAGS) @@ -76,7 +76,8 @@ SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_BasicManagement.cpp SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_Manager.cpp #Include file path -INCLUDES = -I$(SERIAL_INCLUDE_PATH) +INCLUDES = +INCLUDES += -I$(SERIAL_INCLUDE_PATH) # INCLUDES += -I$(COMMUNICATION_INCLUDE_PATH) # INCLUDES += -I$(OTHER_INCLUDE_PATH) diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index d4cef88..a75dee2 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -3,6 +3,9 @@ #if defined(_WIN32) #include +#else +#include +#define _getche getchar #endif #include "TrackPlatform_Manager.h" diff --git a/code/c++/cxx-app/makefile b/code/c++/cxx-app/makefile new file mode 100644 index 0000000..2d62d33 --- /dev/null +++ b/code/c++/cxx-app/makefile @@ -0,0 +1,150 @@ +#Make file to compile source code for track platform cxx api library + +#Project Name +PROJECT_NAME = track-platform_cxx-app +#Build option +BUILD ?= BUILD_STATIC +#ANSI Colos +ANSI_COLOR_RED = \e[31m +ANSI_COLOR_GREEN = \e[32m +ANSI_COLOR_YELLOW = \e[33m +ANSI_COLOR_BLUE = \e[34m +ANSI_COLOR_MAGENTA = \e[35m +ANSI_COLOR_CYAN = \e[36m +ANSI_COLOR_RESET = \e[37m +################################Compiller flags############################################################### +#Opitmization Level +OPT_LEVEL = -O0 +#Warning options +WARNINGS = -Wall -Wpedantic #-Werror +# WARNINGS += -fsyntax-only # for syntax checking only, without comlipation +WARNINGS_WITHOUT = +#User Compiller flags +USER_FLAGS ?= +############################################################################################################## +# OS definition +ifndef OS +OS = other +endif + +#Build patch +BUILD_PATH = Output/$(OS) +OBJ_PATH = $(BUILD_PATH)/obj + +#Compiller flags +CFLAGS = $(OPT_LEVEL) +CFLAGS += -g0 +CFLAGS += $(WARNINGS) +CFLAGS += -I. +CFLAGS += $(USER_FLAGS) +CFLAGS += -std=c++11 +CFLAGS += -D$(BUILD) +# ifeq ($(BUILD), BUILD_STATIC) +# CFLAGS += -D$(BUILD_STATIC) +# endif + +CFLAGS += $(INCLUDES) +############################################################################################################## +#Code file path +OTHER_PATH = . +OTHER_SOURCE_PATH = $(OTHER_PATH) +OTHER_INCLUDE_PATH = $(OTHER_PATH) + +#library path +API_PATH = ../cxx-api +API_INCLUDE_PATH = $(API_PATH) +API_BUILD_PATH = $(API_PATH)/$(BUILD_PATH) + +ifeq ($(BUILD), BUILD_STATIC) +API_NAME = track-platform_cxx-api.a +else +ifeq ($(BUILD), BUILD_DYNAMIC) +API_NAME = track-platform_cxx-api.so +endif +endif + +API_FULL_PATH = $(API_BUILD_PATH)/$(API_NAME) + +#Linker scrpit file +ARFLAGS = + +#Source file path + +SOURCES = +# Other code (non grouped) +SOURCES += $(OTHER_SOURCE_PATH)/main.cpp + +#Include file path +INCLUDES = +INCLUDES += -I$(API_INCLUDE_PATH) +# INCLUDES += -I$(OTHER_INCLUDE_PATH) + +############################################################################################################## +BUILD_PRINT = $(ANSI_COLOR_GREEN) Building:$(ANSI_COLOR_RESET) $@ +############################################################################################################## +#Output files +BIN = $(BUILD_PATH)/$(PROJECT_NAME) + +OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) + +STATIC_LIB: $(OBJECTS) api + @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) + @echo -e "$(BUILD_PRINT)" + +DYNAMIC_LIB: $(OBJECTS) api + $(error Dynamic library is not supported yet) + # @$(CXX) -shared -o $(BIN) $(OBJECTS) + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cc + @mkdir -p $(dir $@) + @$(CXX) -c $(CFLAGS) $< -o $@ + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cpp + @mkdir -p $(dir $@) + @$(CXX) -c $(CFLAGS) $< -o $@ + @echo -e "$(BUILD_PRINT)" + +#Makefile parameters +.DEFAULT_GOAL := all + +all: build + +ifeq ($(BUILD), BUILD_STATIC) +build: STATIC_LIB + +else +ifeq ($(BUILD), BUILD_DYNAMIC) +build: DYNAMIC_LIB + +else +build: + @echo "That BUILD variable is not supported. Use `make help` to see supported variants of build variable" +endif +endif + +dynamic: + $(MAKE) BUILD=BUILD_DYNAMIC + +static: + $(MAKE) BUILD=BUILD_STATIC + +api: + $(MAKE) -C $(API_PATH) BUILD=$(BUILD) + +clean: + @rm -rf $(BUILD_PATH) + +run: + @$(BIN) + +set_def_color: + @echo -e "$(ANSI_COLOR_RESET)" + +help: + @echo "$(NEW_LINE)" + @echo "\tall : Builds static or dynamic library (static by default)" + @echo "\t\tIf you want to build static library(.a file), write `make` or `make static` or `make BUILD=BUILD_DYNAMIC`" + @echo "\t\tIf you want to build dynamic library(.so file), write `make dynamic` or `make BUILD=BUILD_DYNAMIC`" + @echo "$(NEW_LINE)" From 5ee6e1a9020986e69d65c9d6be16e75281cf20fb Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 14 Aug 2017 16:42:01 +0300 Subject: [PATCH 042/336] =?UTF-8?q?*=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D1=83=20?= =?UTF-8?q?=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=81=D0=B5=D0=BD=D1=81=D0=BE=D1=80=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/peripheral/SensorsController.cpp | 4 ++-- code/Arduino/peripheral/SensorsController.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index 0abe9c2..3aa1009 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -128,13 +128,13 @@ void SensorsController::chooseDistanceSensor(int number) { int SensorsController::getDistance(int number) { chooseDistanceSensor(number); float volts = analogRead(constants.distance_sensor_read_pin); - DEBUG_PRINTF("Distance volts: %d\n", (int)volts); if (volts == 0) { DEBUG_PRINTLN("Distance volts were 0"); - return -1; //TODO: crutch + return 0; } float distance = (6762 / (volts)) - 4; + DEBUG_PRINTF("Distance volts = %d, dist * 10000 = %06ld\n", (int)volts, (long)(distance * 10000)); return distance; } diff --git a/code/Arduino/peripheral/SensorsController.h b/code/Arduino/peripheral/SensorsController.h index fff8ec7..a0e7c44 100644 --- a/code/Arduino/peripheral/SensorsController.h +++ b/code/Arduino/peripheral/SensorsController.h @@ -4,6 +4,9 @@ #include "../connectors/ConnectingDevice.h" #include "MainController.h" +/** + * @brief Get information from sensors: line and distance. Distance values are returned in centimeters + */ class SensorsController: public MainController { int countDistanceSensors; From b51cc721fb828907181902904e3f919d9f444d24 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 14 Aug 2017 17:07:19 +0300 Subject: [PATCH 043/336] * platform-dependent -> platform_dependent --- code/c++/cxx-api/cxx-api.vcxproj | 12 ++++++------ code/c++/cxx-api/cxx-api.vcxproj.filters | 8 ++++---- .../windows/TCPIP_Connector.cpp | 0 .../windows/TCPIP_Connector.h | 0 code/c++/cxx-app/main.cpp | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) rename code/c++/cxx-api/{platform-dependent => platform_dependent}/windows/TCPIP_Connector.cpp (100%) rename code/c++/cxx-api/{platform-dependent => platform_dependent}/windows/TCPIP_Connector.h (100%) diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index f6fb778..722a9e6 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -70,22 +70,22 @@ - $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform_dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform_dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform_dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - $(ProjectDir)platform-dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) + $(ProjectDir)platform_dependent\windows\;$(ProjectDir);$(ProjectDir)serial_support\include\;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index ccaafa5..7cd8837 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -84,9 +84,6 @@ exceptions\header - - Communication\header - exceptions\header @@ -96,6 +93,9 @@ exceptions\header + + Communication\header + @@ -122,7 +122,7 @@ exceptions\source - + Communication\source diff --git a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp b/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp similarity index 100% rename from code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.cpp rename to code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp diff --git a/code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h b/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.h similarity index 100% rename from code/c++/cxx-api/platform-dependent/windows/TCPIP_Connector.h rename to code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.h diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 0ecfb20..fd87ea1 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -9,7 +9,7 @@ #endif #include "TrackPlatform_Manager.h" -#include "platform-dependent/windows/TCPIP_Connector.h" +#include "platform_dependent/windows/TCPIP_Connector.h" int main(int argc, char* argv[]) { From 82305749bede9f4421dca047d18cb194d6d3fd71 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 14 Aug 2017 23:57:12 +0300 Subject: [PATCH 044/336] =?UTF-8?q?*=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B0=20linux=20socket=20*=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF?= =?UTF-8?q?=D0=B8=D0=BB=D1=8F=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BB=D0=B0=D1=82?= =?UTF-8?q?=D1=84=D0=BE=D1=80=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BE=D0=B4=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5=D0=BC=20makefile=20*=20=D0=9D=D1=83?= =?UTF-8?q?=D0=B6=D0=BD=D0=BE=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B1=D0=B0=D0=B3=20=D0=BA=D0=BE=D0=BC=D0=BF?= =?UTF-8?q?=D0=B8=D0=BB=D1=8F=D1=86=D0=B8=D0=B8=20(std::exception)=20*=20?= =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B1=D0=B0=D0=B3?= =?UTF-8?q?=20=D1=81=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=D0=BC=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9,=20=D0=BF=D1=80=D0=B5=D0=B2=D1=8B=D1=88=D0=B0=D1=8E?= =?UTF-8?q?=D1=89=D0=B8=D1=85=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B1=D1=83=D1=84=D0=B5=D1=80=D0=B0=20(=D0=B8=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD,=20=D0=BD?= =?UTF-8?q?=D1=83=D0=B6=D0=BD=D0=BE=20=D0=BF=D1=80=D0=BE=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/makefile | 18 +- .../Linux/TCPIP_Connector.cpp | 167 ++++++++++++++++++ .../Linux/TCPIP_Connector.h | 53 ++++++ .../windows/TCPIP_Connector.cpp | 4 +- code/c++/cxx-app/main.cpp | 4 + code/c++/cxx-app/makefile | 7 +- 6 files changed, 243 insertions(+), 10 deletions(-) create mode 100644 code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp create mode 100644 code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h diff --git a/code/c++/cxx-api/makefile b/code/c++/cxx-api/makefile index 8bc9b5d..c0d55e7 100644 --- a/code/c++/cxx-api/makefile +++ b/code/c++/cxx-api/makefile @@ -22,10 +22,8 @@ WARNINGS_WITHOUT = #User Compiller flags USER_FLAGS ?= ############################################################################################################## -# OS definition -ifndef OS -OS = other -endif +# OS redefinition +OS = $(shell uname -s) #Build patch BUILD_PATH = Output/$(OS) @@ -54,6 +52,12 @@ SERIAL_INCLUDE_PATH = $(SERIAL_PATH)/include COMMUNICATION_PATH = . COMMUNICATION_SOURCE_PATH = $(COMMUNICATION_PATH) COMMUNICATION_INCLUDE_PATH = $(COMMUNICATION_PATH) +PLATFORM_DEPENDENT_PATH = platform_dependent/$(OS) +PLATFORM_DEPENDENT_SOURCE_PATH = $(PLATFORM_DEPENDENT_PATH) +PLATFORM_DEPENDENT_INCLUDE_PATH = $(PLATFORM_DEPENDENT_PATH) +EXCEPTION_PATH = . +EXCEPTION_SOURCE_PATH = $(EXCEPTION_PATH) +EXCEPTION_INCLUDE_PATH = $(EXCEPTION_PATH) OTHER_PATH = . OTHER_SOURCE_PATH = $(OTHER_PATH) OTHER_INCLUDE_PATH = $(OTHER_PATH) @@ -71,6 +75,10 @@ SOURCES += $(SERIAL_SOURCE_LIST_PORTS_PATH)/list_ports_linux.cc # Communication SOURCES += $(COMMUNICATION_SOURCE_PATH)/TrackPlatform_BasicConnector.cpp SOURCES += $(COMMUNICATION_SOURCE_PATH)/SerialConnector.cpp +# Platform-dependent sources +SOURCES += $(PLATFORM_DEPENDENT_SOURCE_PATH)/TCPIP_Connector.cpp +# Exceptions sources +SOURCES += $(EXCEPTION_SOURCE_PATH)/TrackPlatformException.cpp # Other code (non grouped) SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_BasicManagement.cpp SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_Manager.cpp @@ -79,6 +87,8 @@ SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_Manager.cpp INCLUDES = INCLUDES += -I$(SERIAL_INCLUDE_PATH) # INCLUDES += -I$(COMMUNICATION_INCLUDE_PATH) +INCLUDES += -I$(PLATFORM_DEPENDENT_INCLUDE_PATH) +# INCLUDES += -I$(EXCEPTION_INCLUDE_PATH) # INCLUDES += -I$(OTHER_INCLUDE_PATH) ############################################################################################################## diff --git a/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp b/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp new file mode 100644 index 0000000..7033eae --- /dev/null +++ b/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp @@ -0,0 +1,167 @@ +#if !(defined(__linux__) || defined(__unix__)) + +#error This source file must be used only on linux or unix platforms + +#else /* !(defined(__linux__) || defined(__unix__)) */ + +#define SOCKET_ERROR (-1) +#define closesocket(...) close(__VA_ARGS__) + +/* shutdown() ports */ +#define SD_RECEIVE SHUT_RD +#define SD_SEND SHUT_WR +#define SD_BOTH SHUT_RDWR + +#define WSAGetLastError() errno + +#include +#include +#include +#include +#include +#include + +#include + +#include "trackPlatformAllExceptions.h" +#include "TCPIP_Connector.h" + +void TCPIP_Connector::write(const std::string& s) +{ + // Send an initial buffer (returns byte sended) + int iResult = send(connectedSocket, s.c_str(), s.length(), 0); + if (iResult == SOCKET_ERROR) { + throw SocketSendException(WSAGetLastError()); + } +} + +std::string TCPIP_Connector::read() +{ + std::string answer; + char recvbuf[onePacketMaxSize]; + + int iResult; + + do { + // Check if something is already in buffer (and wait `microsecondsToWaitAnswer` if required) + timeval tval = { 0, microsecondsToWaitAnswer }; + fd_set readSockets; + FD_ZERO(&readSockets); + FD_SET(connectedSocket, &readSockets); + iResult = select(connectedSocket + 1, &readSockets, NULL, NULL, &tval); + if (iResult == SOCKET_ERROR) + { + throw SocketException(WSAGetLastError()); + } + if (iResult == 0) + { + break; + } + + // Receive data until the server closes the connection + iResult = recv(connectedSocket, recvbuf, sizeof(recvbuf), 0); + if (iResult < 0) + { + throw SocketReceiveException(WSAGetLastError()); + } + + answer += std::string(recvbuf, iResult); + } while (iResult > 0); + + return answer; +} + +void TCPIP_Connector::configureSocket() +{ + struct addrinfo hints; + + // Configure socket + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* AF_UNSPEC for IPv6 or IPv4 (automatically); AF_INET6 for IPv6; AF_INET for IPv4 */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + // Resolve the server address and port + int iResult = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &addressInfo); + if (iResult != 0) { + addressInfo = nullptr; + throw BadAddressOrPortException(iResult); + } +} + +void TCPIP_Connector::closeSocket() +{ + if (connectedSocket != INVALID_SOCKET) + { + closesocket(connectedSocket); + connectedSocket = INVALID_SOCKET; + } +} + +bool TCPIP_Connector::isConnected() +{ + return isConnected_private; +} + +void TCPIP_Connector::connect() +{ + if (isConnected_private) { + return; + } + + // Attempt to connect to the first address returned by + // the call to getaddrinfo + struct addrinfo* ptr = addressInfo; + + // Create a SOCKET for connecting to server + connectedSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + + if (connectedSocket == INVALID_SOCKET) { + throw SocketException(WSAGetLastError()); + } + + // Connect to server. + int iResult = ::connect(connectedSocket, addressInfo->ai_addr, addressInfo->ai_addrlen); + if (iResult == SOCKET_ERROR) { + closeSocket(); + } + else + { + isConnected_private = true; + } +} + +void TCPIP_Connector::disconnect() +{ + if (!isConnected_private) + { + return; + } + + // shutdown the sending and recieving data by socket + int iResult = shutdown(connectedSocket, SD_BOTH); + if (iResult == SOCKET_ERROR) { + throw SocketShutdownException(WSAGetLastError()); + } + + closeSocket(); + isConnected_private = false; +} + +TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) + : ip(ip), port(port) +{ + configureSocket(); + TCPIP_Connector::connect(); +} + +TCPIP_Connector::~TCPIP_Connector() +{ + TCPIP_Connector::disconnect(); + if (addressInfo) + { + freeaddrinfo(addressInfo); + } +} + +#endif /* !(defined(__linux__) || defined(__unix__)) */ diff --git a/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h b/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h new file mode 100644 index 0000000..3639934 --- /dev/null +++ b/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h @@ -0,0 +1,53 @@ +#ifndef _TCPIP_CONNECTOR_H_ +#define _TCPIP_CONNECTOR_H_ + +#if !(defined(__linux__) || defined(__unix__)) + +#error This header file must be used only on linux or unix platforms + +#else /* !(defined(__linux__) || defined(__unix__)) */ + +#define SOCKET int +#define INVALID_SOCKET (-1) + +#include "TrackPlatform_BasicConnector.h" + +class TCPIP_Connector : public TrackPlatform_BasicConnector +{ + std::string ip; + uint16_t port; + + static const uint16_t onePacketMaxSize = 512; + static const int32_t microsecondsToWaitAnswer = 100000; + + struct addrinfo *addressInfo = nullptr; + SOCKET connectedSocket = INVALID_SOCKET; + + bool isConnected_private = false; + + void configureSocket(); + void closeSocket(); + +protected: + void write(const std::string& s) override; + std::string read() override; + +public: + /** + * @brief Create TCP/IP connector to trackPlatform + * @warning Only one object of that class in one moment of time is supported + * + * @param ip IP of trackPlatform Wi-Fi module + * @warning Supports only single IP, no masks + * @param port Port of TCP/IP server on trackPlatform + */ + TCPIP_Connector(const std::string& ip, uint16_t port); + virtual ~TCPIP_Connector(); + + bool isConnected() override; + void connect() override; + void disconnect() override; +}; + +#endif /* !(defined(__linux__) || defined(__unix__)) */ +#endif /* _TCPIP_CONNECTOR_H_ */ diff --git a/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp b/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp index 8b68869..a64734f 100644 --- a/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp @@ -1,6 +1,6 @@ #ifndef _WIN32 -#error This source file must be used only on Windows desktop platforms (win32) +#error This source file must be used only on Windows desktop platforms (win32) #else /* _WIN32 */ @@ -32,7 +32,7 @@ std::string TCPIP_Connector::read() { throw SocketException(WSAGetLastError()); } - if (iResult > 0) + if (iResult == 0) { break; } diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index fd87ea1..5f91d57 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -9,7 +9,11 @@ #endif #include "TrackPlatform_Manager.h" +#if defined(_WIN32) #include "platform_dependent/windows/TCPIP_Connector.h" +#else +#include "platform_dependent/Linux/TCPIP_Connector.h" +#endif int main(int argc, char* argv[]) { diff --git a/code/c++/cxx-app/makefile b/code/c++/cxx-app/makefile index 2d62d33..f400c40 100644 --- a/code/c++/cxx-app/makefile +++ b/code/c++/cxx-app/makefile @@ -22,10 +22,8 @@ WARNINGS_WITHOUT = #User Compiller flags USER_FLAGS ?= ############################################################################################################## -# OS definition -ifndef OS -OS = other -endif +# OS redefinition +OS = $(shell uname -s) #Build patch BUILD_PATH = Output/$(OS) @@ -135,6 +133,7 @@ api: clean: @rm -rf $(BUILD_PATH) + $(MAKE) -C $(API_PATH) $@ run: @$(BIN) From c11dce493921ab8b249a4034e65656d03bc764c3 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 15 Aug 2017 09:54:45 +0300 Subject: [PATCH 045/336] =?UTF-8?q?*=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8?= =?UTF-8?q?=D0=BB=D1=8F=D1=86=D0=B8=D1=8F=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BF=D0=BE=D0=B4=20=D0=9E?= =?UTF-8?q?=D0=A1=20linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatformException.cpp | 14 ++++++++++++++ code/c++/cxx-api/TrackPlatformException.h | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/code/c++/cxx-api/TrackPlatformException.cpp b/code/c++/cxx-api/TrackPlatformException.cpp index d2af835..f6435e9 100644 --- a/code/c++/cxx-api/TrackPlatformException.cpp +++ b/code/c++/cxx-api/TrackPlatformException.cpp @@ -4,7 +4,21 @@ TrackPlatformException::TrackPlatformException() { } +#ifdef _WIN32 TrackPlatformException::TrackPlatformException(const std::string& errorMessage) : std::exception(errorMessage.c_str()) { } + +#else /* _WIN32 */ +TrackPlatformException::TrackPlatformException(const std::string& errorMessage) + : errorText(errorMessage) +{ +} + +const char* TrackPlatformException::what() const noexcept +{ + return errorText.c_str(); +} + +#endif /* _WIN32 */ diff --git a/code/c++/cxx-api/TrackPlatformException.h b/code/c++/cxx-api/TrackPlatformException.h index 93ccb98..5bd7566 100644 --- a/code/c++/cxx-api/TrackPlatformException.h +++ b/code/c++/cxx-api/TrackPlatformException.h @@ -6,9 +6,17 @@ class TrackPlatformException : public std::exception { +#ifndef _WIN32 + std::string errorText; +#endif /* _WIN32 */ + public: TrackPlatformException(); explicit TrackPlatformException(const std::string& errorMessage); + +#ifndef _WIN32 + const char* what() const noexcept override; +#endif /* _WIN32 */ }; #endif /* _TRACK_PLATFORM_EXCEPTION_H_ */ From 3b838fdbb6a4a1f6dbc959750eece6300987b0b3 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 15 Aug 2017 11:32:15 +0300 Subject: [PATCH 046/336] =?UTF-8?q?*=20=D0=9E=D0=B1=D1=8A=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=D1=8B=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B?= =?UTF-8?q?=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20TCP/IP=20=D0=B8=D0=B7-=D0=B7=D0=B0=20=D0=BE=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D1=8C=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=BE=D0=B9=20?= =?UTF-8?q?=D1=81=D1=85=D0=BE=D0=B6=D0=B5=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Linux => }/TCPIP_Connector.cpp | 34 +++- .../windows => }/TCPIP_Connector.h | 22 ++- code/c++/cxx-api/cxx-api.vcxproj | 4 +- code/c++/cxx-api/cxx-api.vcxproj.filters | 4 +- code/c++/cxx-api/makefile | 10 +- .../Linux/TCPIP_Connector.h | 53 ------ .../windows/TCPIP_Connector.cpp | 153 ------------------ 7 files changed, 51 insertions(+), 229 deletions(-) rename code/c++/cxx-api/{platform_dependent/Linux => }/TCPIP_Connector.cpp (82%) rename code/c++/cxx-api/{platform_dependent/windows => }/TCPIP_Connector.h (83%) delete mode 100644 code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h delete mode 100644 code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp diff --git a/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp similarity index 82% rename from code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp rename to code/c++/cxx-api/TCPIP_Connector.cpp index 7033eae..68a1ef9 100644 --- a/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/TCPIP_Connector.cpp @@ -1,8 +1,4 @@ -#if !(defined(__linux__) || defined(__unix__)) - -#error This source file must be used only on linux or unix platforms - -#else /* !(defined(__linux__) || defined(__unix__)) */ +#if (defined(__linux__) || defined(__unix__)) #define SOCKET_ERROR (-1) #define closesocket(...) close(__VA_ARGS__) @@ -21,6 +17,8 @@ #include #include +#endif /* (defined(__linux__) || defined(__unix__)) */ + #include #include "trackPlatformAllExceptions.h" @@ -29,7 +27,11 @@ void TCPIP_Connector::write(const std::string& s) { // Send an initial buffer (returns byte sended) +#ifdef _WIN32 + int iResult = send(connectedSocket, s.c_str(), static_cast(s.length()), 0); +#else /* _WIN32 */ int iResult = send(connectedSocket, s.c_str(), s.length(), 0); +#endif /* _WIN32 */ if (iResult == SOCKET_ERROR) { throw SocketSendException(WSAGetLastError()); } @@ -45,10 +47,16 @@ std::string TCPIP_Connector::read() do { // Check if something is already in buffer (and wait `microsecondsToWaitAnswer` if required) timeval tval = { 0, microsecondsToWaitAnswer }; + +#ifdef _WIN32 + fd_set readSockets = { 1, { connectedSocket } }; + iResult = select(0, &readSockets, NULL, NULL, &tval); +#else /* _WIN32 */ fd_set readSockets; FD_ZERO(&readSockets); FD_SET(connectedSocket, &readSockets); iResult = select(connectedSocket + 1, &readSockets, NULL, NULL, &tval); +#endif /* _WIN32 */ if (iResult == SOCKET_ERROR) { throw SocketException(WSAGetLastError()); @@ -121,7 +129,11 @@ void TCPIP_Connector::connect() } // Connect to server. +#ifdef _WIN32 + int iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); +#else /* _WIN32 */ int iResult = ::connect(connectedSocket, addressInfo->ai_addr, addressInfo->ai_addrlen); +#endif /* _WIN32 */ if (iResult == SOCKET_ERROR) { closeSocket(); } @@ -151,6 +163,14 @@ void TCPIP_Connector::disconnect() TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) : ip(ip), port(port) { +#ifdef _WIN32 + // Initialize Winsock + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != 0) { + throw WSAStartupException(iResult); + } +#endif + configureSocket(); TCPIP_Connector::connect(); } @@ -162,6 +182,8 @@ TCPIP_Connector::~TCPIP_Connector() { freeaddrinfo(addressInfo); } +#ifdef _WIN32 + WSACleanup(); +#endif } -#endif /* !(defined(__linux__) || defined(__unix__)) */ diff --git a/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.h b/code/c++/cxx-api/TCPIP_Connector.h similarity index 83% rename from code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.h rename to code/c++/cxx-api/TCPIP_Connector.h index ffdb1ab..019703f 100644 --- a/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.h +++ b/code/c++/cxx-api/TCPIP_Connector.h @@ -1,11 +1,7 @@ -#ifndef _TCPIP_CONNECTOR_H_ +#ifndef _TCPIP_CONNECTOR_H_ #define _TCPIP_CONNECTOR_H_ -#ifndef _WIN32 - -#error This header file must be used only on Windows desktop platforms (win32) - -#else /* _WIN32 */ +#if defined(_WIN32) /* WinAPI include */ #ifndef WIN32_LEAN_AND_MEAN @@ -19,6 +15,15 @@ #pragma comment(lib, "Ws2_32.lib") +#endif /* _WIN32 */ + +#if (defined(__linux__) || defined(__unix__)) + +#define SOCKET int +#define INVALID_SOCKET (-1) + +#endif /* (defined(__linux__) || defined(__unix__)) */ + #include "TrackPlatform_BasicConnector.h" class TCPIP_Connector : public TrackPlatform_BasicConnector @@ -29,7 +34,9 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector static const uint16_t onePacketMaxSize = 512; static const int32_t microsecondsToWaitAnswer = 100000; +#ifdef _WIN32 WSADATA wsaData; +#endif /* _WIN32 */ struct addrinfo *addressInfo = nullptr; SOCKET connectedSocket = INVALID_SOCKET; @@ -46,7 +53,7 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector /** * @brief Create TCP/IP connector to trackPlatform * @warning Only one object of that class in one moment of time is supported - * + * * @param ip IP of trackPlatform Wi-Fi module * @warning Supports only single IP, no masks * @param port Port of TCP/IP server on trackPlatform @@ -59,5 +66,4 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector void disconnect() override; }; -#endif /* _WIN32 */ #endif /* _TCPIP_CONNECTOR_H_ */ diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 722a9e6..16370f4 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -147,7 +147,6 @@ - @@ -158,6 +157,7 @@ + @@ -166,11 +166,11 @@ - + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 7cd8837..333d6ab 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -93,7 +93,7 @@ exceptions\header - + Communication\header @@ -122,7 +122,7 @@ exceptions\source - + Communication\source diff --git a/code/c++/cxx-api/makefile b/code/c++/cxx-api/makefile index c0d55e7..cfbf30f 100644 --- a/code/c++/cxx-api/makefile +++ b/code/c++/cxx-api/makefile @@ -52,9 +52,9 @@ SERIAL_INCLUDE_PATH = $(SERIAL_PATH)/include COMMUNICATION_PATH = . COMMUNICATION_SOURCE_PATH = $(COMMUNICATION_PATH) COMMUNICATION_INCLUDE_PATH = $(COMMUNICATION_PATH) -PLATFORM_DEPENDENT_PATH = platform_dependent/$(OS) -PLATFORM_DEPENDENT_SOURCE_PATH = $(PLATFORM_DEPENDENT_PATH) -PLATFORM_DEPENDENT_INCLUDE_PATH = $(PLATFORM_DEPENDENT_PATH) +# PLATFORM_DEPENDENT_PATH = platform_dependent/$(OS) +# PLATFORM_DEPENDENT_SOURCE_PATH = $(PLATFORM_DEPENDENT_PATH) +# PLATFORM_DEPENDENT_INCLUDE_PATH = $(PLATFORM_DEPENDENT_PATH) EXCEPTION_PATH = . EXCEPTION_SOURCE_PATH = $(EXCEPTION_PATH) EXCEPTION_INCLUDE_PATH = $(EXCEPTION_PATH) @@ -75,8 +75,8 @@ SOURCES += $(SERIAL_SOURCE_LIST_PORTS_PATH)/list_ports_linux.cc # Communication SOURCES += $(COMMUNICATION_SOURCE_PATH)/TrackPlatform_BasicConnector.cpp SOURCES += $(COMMUNICATION_SOURCE_PATH)/SerialConnector.cpp +SOURCES += $(COMMUNICATION_SOURCE_PATH)/TCPIP_Connector.cpp # Platform-dependent sources -SOURCES += $(PLATFORM_DEPENDENT_SOURCE_PATH)/TCPIP_Connector.cpp # Exceptions sources SOURCES += $(EXCEPTION_SOURCE_PATH)/TrackPlatformException.cpp # Other code (non grouped) @@ -87,7 +87,7 @@ SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_Manager.cpp INCLUDES = INCLUDES += -I$(SERIAL_INCLUDE_PATH) # INCLUDES += -I$(COMMUNICATION_INCLUDE_PATH) -INCLUDES += -I$(PLATFORM_DEPENDENT_INCLUDE_PATH) +# INCLUDES += -I$(PLATFORM_DEPENDENT_INCLUDE_PATH) # INCLUDES += -I$(EXCEPTION_INCLUDE_PATH) # INCLUDES += -I$(OTHER_INCLUDE_PATH) diff --git a/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h b/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h deleted file mode 100644 index 3639934..0000000 --- a/code/c++/cxx-api/platform_dependent/Linux/TCPIP_Connector.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _TCPIP_CONNECTOR_H_ -#define _TCPIP_CONNECTOR_H_ - -#if !(defined(__linux__) || defined(__unix__)) - -#error This header file must be used only on linux or unix platforms - -#else /* !(defined(__linux__) || defined(__unix__)) */ - -#define SOCKET int -#define INVALID_SOCKET (-1) - -#include "TrackPlatform_BasicConnector.h" - -class TCPIP_Connector : public TrackPlatform_BasicConnector -{ - std::string ip; - uint16_t port; - - static const uint16_t onePacketMaxSize = 512; - static const int32_t microsecondsToWaitAnswer = 100000; - - struct addrinfo *addressInfo = nullptr; - SOCKET connectedSocket = INVALID_SOCKET; - - bool isConnected_private = false; - - void configureSocket(); - void closeSocket(); - -protected: - void write(const std::string& s) override; - std::string read() override; - -public: - /** - * @brief Create TCP/IP connector to trackPlatform - * @warning Only one object of that class in one moment of time is supported - * - * @param ip IP of trackPlatform Wi-Fi module - * @warning Supports only single IP, no masks - * @param port Port of TCP/IP server on trackPlatform - */ - TCPIP_Connector(const std::string& ip, uint16_t port); - virtual ~TCPIP_Connector(); - - bool isConnected() override; - void connect() override; - void disconnect() override; -}; - -#endif /* !(defined(__linux__) || defined(__unix__)) */ -#endif /* _TCPIP_CONNECTOR_H_ */ diff --git a/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp b/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp deleted file mode 100644 index a64734f..0000000 --- a/code/c++/cxx-api/platform_dependent/windows/TCPIP_Connector.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef _WIN32 - -#error This source file must be used only on Windows desktop platforms (win32) - -#else /* _WIN32 */ - -#include "trackPlatformAllExceptions.h" -#include "TCPIP_Connector.h" - -void TCPIP_Connector::write(const std::string& s) -{ - // Send an initial buffer (returns byte sended) - int iResult = send(connectedSocket, s.c_str(), static_cast(s.length()), 0); - if (iResult == SOCKET_ERROR) { - throw SocketSendException(WSAGetLastError()); - } -} - -std::string TCPIP_Connector::read() -{ - std::string answer; - char recvbuf[onePacketMaxSize]; - - int iResult; - - do { - // Check if something is already in buffer (and wait `microsecondsToWaitAnswer` if required) - timeval tval = { 0, microsecondsToWaitAnswer }; - fd_set readSockets = { 1, { connectedSocket } }; - iResult = select(NULL, &readSockets, NULL, NULL, &tval); - if (iResult == SOCKET_ERROR) - { - throw SocketException(WSAGetLastError()); - } - if (iResult == 0) - { - break; - } - - // Receive data until the server closes the connection - iResult = recv(connectedSocket, recvbuf, sizeof(recvbuf), 0); - if (iResult < 0) - { - throw SocketReceiveException(WSAGetLastError()); - } - - answer += std::string(recvbuf, iResult); - } while (iResult > 0); - - return answer; -} - -void TCPIP_Connector::configureSocket() -{ - struct addrinfo hints; - - // Configure socket - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* AF_UNSPEC for IPv6 or IPv4 (automatically); AF_INET6 for IPv6; AF_INET for IPv4 */ - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - // Resolve the server address and port - int iResult = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &addressInfo); - if (iResult != 0) { - addressInfo = nullptr; - throw BadAddressOrPortException(iResult); - } -} - -void TCPIP_Connector::closeSocket() -{ - if (connectedSocket != INVALID_SOCKET) - { - closesocket(connectedSocket); - connectedSocket = INVALID_SOCKET; - } -} - -bool TCPIP_Connector::isConnected() -{ - return isConnected_private; -} - -void TCPIP_Connector::connect() -{ - if (isConnected_private) { - return; - } - - // Attempt to connect to the first address returned by - // the call to getaddrinfo - struct addrinfo* ptr = addressInfo; - - // Create a SOCKET for connecting to server - connectedSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); - - if (connectedSocket == INVALID_SOCKET) { - throw SocketException(WSAGetLastError()); - } - - // Connect to server. - int iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); - if (iResult == SOCKET_ERROR) { - closeSocket(); - } - else - { - isConnected_private = true; - } -} - -void TCPIP_Connector::disconnect() -{ - if (!isConnected_private) - { - return; - } - - // shutdown the sending and recieving data by socket - int iResult = shutdown(connectedSocket, SD_BOTH); - if (iResult == SOCKET_ERROR) { - throw SocketShutdownException(WSAGetLastError()); - } - - closeSocket(); - isConnected_private = false; -} - -TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) - : ip(ip), port(port) -{ - // Initialize Winsock - int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) { - throw WSAStartupException(iResult); - } - - configureSocket(); - TCPIP_Connector::connect(); -} - -TCPIP_Connector::~TCPIP_Connector() -{ - TCPIP_Connector::disconnect(); - if (addressInfo) - { - freeaddrinfo(addressInfo); - } - WSACleanup(); -} - -#endif /* _WIN32 */ From e7de7bd0f2fdc535df6d04f1f07476e3c46db004 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Wed, 16 Aug 2017 23:53:57 +0300 Subject: [PATCH 047/336] =?UTF-8?q?=D0=A7=D0=B0=D1=81=D1=82=D0=B8=D1=87?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=20Wi-?= =?UTF-8?q?Fi=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 48 +++++++++++++++++++------------- code/Arduino/connectors/WiFi.h | 35 +++++++++++++++-------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index cb7b4ae..f7874f1 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -4,8 +4,14 @@ WiFi::WiFi(int rx, int tx, int speed) : ConnectingDevice(rx, tx, speed) { - Check(); - ChangeSpeed(speed); + if (Check()) + { + ChangeSpeed(speed); + } + else + { + Reset(speed); + } } WiFi::~WiFi() @@ -18,7 +24,7 @@ String WiFi::VersionCheck() return read(); } -String CheckIPandMAC() +String WiFi::CheckIPandMAC() { send("AT+CIFSR"); return read(); @@ -28,18 +34,25 @@ void WiFi::ChangeSpeed(int speed) { if (ready) { - send("AT+CIOBAUD=" + speed); + send("AT+CIOBAUD=" + String(speed)); } } -void WiFi::Reset(int speed) +bool WiFi::Reset() { send("AT+RST"); - Check(); + ready = (read() == "OK"); + return ready; +} + +bool WiFi::Reset(int speed) +{ + ready = Reset(); ChangeSpeed(speed); + return ready; } -void WiFi::CurrentLog(String name, String password, int port) +void WiFi::CreateCurrentHost(String name, String password, int port) { if (ready) { @@ -52,7 +65,7 @@ void WiFi::CurrentLog(String name, String password, int port) } } -void WiFi::StaticLog(String name, String password, int port) +void WiFi::CreateStaticHost(String name, String password, int port) { if (ready) { @@ -93,20 +106,17 @@ void WiFi::Open() void WiFi::UseTCP(int port) { send("AT+CIPMUX=1"); - send("AT+CIPSERVER=1," + port); + send("AT+CIPSERVER=1," + String(port)); } -void WiFi::Check() +bool WiFi::Check() { send("AT"); - if (read() == "OK") - { - ready = true; - Close(); - } - else - { - ready = false; - } + ready = (read() == "OK"); + return ready; } +void WiFi::send(String command) +{ + ConnectingDevice::send(command + "\r\n"); +} \ No newline at end of file diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 75b389b..26c89f8 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -8,39 +8,48 @@ class WiFi : public ConnectingDevice ~WiFi(); /** - * - * String + * @brief + * @return String */ virtual String VersionCheck(); /** - * - * String + * @brief + * @ String */ virtual String NetsList(); /** - * IP MAC - * String + * @brief IP MAC + * @ String */ virtual String CheckIPandMAC(); /** - * - * + * @ + * @param speed + . , , - . , */ virtual void ChangeSpeed(int speed); + /** + * + * String + */ + virtual bool Reset(); + /** * * + * String */ - virtual void Reset(int speed); + virtual bool Reset(int speed); /** * + * bool */ - virtual void Check(); + virtual bool Check(); /** * @@ -62,13 +71,15 @@ class WiFi : public ConnectingDevice * * String, String int UseTCP */ - virtual void CurrentLog(String name, String password, int port); + virtual void CreateCurrentHost(String name, String password, int port); /** * * String, String int UseTCP */ - virtual void StaticLog(String name, String password, int port); + virtual void CreateStaticHost(String name, String password, int port); + + void send(String command) override; private: From fad07fec9d3508f718d503218f6fd5194b154713 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 17 Aug 2017 09:33:53 +0300 Subject: [PATCH 048/336] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 3 + code/c++/cxx-gamepad-app/.gitignore | 299 ++++++++++++++++++ code/c++/cxx-gamepad-app/GamepadConfig.cpp | 1 + code/c++/cxx-gamepad-app/GamepadConfig.h | 14 + code/c++/cxx-gamepad-app/GamepadManager.cpp | 124 ++++++++ code/c++/cxx-gamepad-app/GamepadManager.h | 16 + code/c++/cxx-gamepad-app/cxx-gamepad-app.sln | 52 +++ .../cxx-gamepad-app/cxx-gamepad-app.vcxproj | 174 ++++++++++ .../cxx-gamepad-app.vcxproj.filters | 42 +++ .../c++/cxx-gamepad-app/gamepad_callbacks.cpp | 13 + code/c++/cxx-gamepad-app/gamepad_callbacks.h | 20 ++ code/c++/cxx-gamepad-app/gamepad_support | 1 + code/c++/cxx-gamepad-app/main.cpp | 29 ++ code/c++/cxx-gamepad-app/makefile | 149 +++++++++ 14 files changed, 937 insertions(+) create mode 100644 code/c++/cxx-gamepad-app/.gitignore create mode 100644 code/c++/cxx-gamepad-app/GamepadConfig.cpp create mode 100644 code/c++/cxx-gamepad-app/GamepadConfig.h create mode 100644 code/c++/cxx-gamepad-app/GamepadManager.cpp create mode 100644 code/c++/cxx-gamepad-app/GamepadManager.h create mode 100644 code/c++/cxx-gamepad-app/cxx-gamepad-app.sln create mode 100644 code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj create mode 100644 code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters create mode 100644 code/c++/cxx-gamepad-app/gamepad_callbacks.cpp create mode 100644 code/c++/cxx-gamepad-app/gamepad_callbacks.h create mode 160000 code/c++/cxx-gamepad-app/gamepad_support create mode 100644 code/c++/cxx-gamepad-app/main.cpp create mode 100644 code/c++/cxx-gamepad-app/makefile diff --git a/.gitmodules b/.gitmodules index 1486cf7..47720d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "cxx_serial_support"] path = code/c++/cxx-api/serial_support url = git@github.com:wjwwood/serial.git +[submodule "cxx_gamepad_support"] + path = code/c++/cxx-gamepad-app/gamepad_support + url = git@github.com:ThemsAllTook/libstem_gamepad.git diff --git a/code/c++/cxx-gamepad-app/.gitignore b/code/c++/cxx-gamepad-app/.gitignore new file mode 100644 index 0000000..1d434d3 --- /dev/null +++ b/code/c++/cxx-gamepad-app/.gitignore @@ -0,0 +1,299 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# AJIOB_Exclude +Output +Build* diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.cpp b/code/c++/cxx-gamepad-app/GamepadConfig.cpp new file mode 100644 index 0000000..afcadc1 --- /dev/null +++ b/code/c++/cxx-gamepad-app/GamepadConfig.cpp @@ -0,0 +1 @@ +#include "GamepadConfig.h" diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.h b/code/c++/cxx-gamepad-app/GamepadConfig.h new file mode 100644 index 0000000..7141864 --- /dev/null +++ b/code/c++/cxx-gamepad-app/GamepadConfig.h @@ -0,0 +1,14 @@ +#ifndef _GAMEPAD_CONFIG_H_ +#define _GAMEPAD_CONFIG_H_ + +typedef enum +{ + +} GamepadCommands; + +class GamepadConfig +{ +public: +}; + +#endif /* _GAMEPAD_CONFIG_H_ */ diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp new file mode 100644 index 0000000..913242d --- /dev/null +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -0,0 +1,124 @@ +#include "TrackPlatform_Manager.h" +#include "gamepad/Gamepad.h" +#include "gamepad_callbacks.h" + +#include "GamepadManager.h" + +GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), isNeedToExit(new bool(false)) +{ + Gamepad_buttonDownFunc(onButtonDown, (void *)trackPlatform); + Gamepad_buttonUpFunc(onButtonUp, (void *)isNeedToExit); + Gamepad_axisMoveFunc(onAxisMoved, (void *)trackPlatform); + Gamepad_init(); +} + +GamepadManager::~GamepadManager() +{ + if (isNeedToExit) + { + delete isNeedToExit; + } + Gamepad_shutdown(); +} + +void GamepadManager::run() +{ + Gamepad_detectDevices(); + Gamepad_processEvents(); + + //bool isExit = false; + //while (!isExit) + //{ + // //std::cout << "Input command, please (0 to help): "; + // auto c = 0; + // //std::cout << std::endl; + + // switch (c) + // { + // case '0': + // //std::cout << "0: help" << std::endl; + // //std::cout << "q: quit" << std::endl; + // //std::cout << "w: move forward" << std::endl; + // //std::cout << "s: move back" << std::endl; + // //std::cout << "a: turn left (anticlockwise)" << std::endl; + // //std::cout << "d: turn right (clockwise)" << std::endl; + // //std::cout << " : stop" << std::endl; + // //std::cout << "r: get all line values" << std::endl; + // //std::cout << "e: get fixed line value" << std::endl; + // //std::cout << "t: get all distance values" << std::endl; + // //std::cout << "y: get fixed distance value" << std::endl; + // //std::cout << "g: set horisontal servo angle in degree" << std::endl; + // //std::cout << "h: set vertical servo angle in degree" << std::endl; + // break; + // case 'q': + // isExit = true; + // break; + // case 'w': + // trackPlatform.moveForward(); + // break; + // case 'a': + // trackPlatform.moveBackward(); + // break; + // case 's': + // trackPlatform.rotateAntiClockwise(); + // break; + // case 'd': + // trackPlatform.rotateClockwise(); + // break; + // case ' ': + // trackPlatform.moveStopAll(); + // break; + // case 'r': + // { + // auto arr = trackPlatform.sensorLineGetAllValues(); + // for (auto a : arr) + // { + // //std::cout << a << std::endl; + // } + // break; + // } + // case 'e': + // { + // //std::cout << "Input num: "; + // int a; + // //std::cin >> a; + // //std::cout << "Value: " << trackPlatform.sensorLineGetValue(a) << std::endl; + // break; + // } + // case 't': + // { + // auto arr = trackPlatform.sensorDistanceGetAllValues(); + // for (auto a : arr) + // { + // //std::cout << a << std::endl; + // } + // break; + // } + // case 'y': + // { + // //std::cout << "Input num: "; + // int a; + // //std::cin >> a; + // //std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a) << std::endl; + // break; + // } + // case 'g': + // { + // //std::cout << "Input num: "; + // int a; + // //std::cin >> a; + // trackPlatform.servoSetHorizontalAngle(a); + // break; + // } + // case 'h': + // { + // //std::cout << "Input num: "; + // int a; + // //std::cin >> a; + // trackPlatform.servoSetVerticalAngle(a); + // break; + // } + // default: break; + // } + //} +} diff --git a/code/c++/cxx-gamepad-app/GamepadManager.h b/code/c++/cxx-gamepad-app/GamepadManager.h new file mode 100644 index 0000000..a2dfe41 --- /dev/null +++ b/code/c++/cxx-gamepad-app/GamepadManager.h @@ -0,0 +1,16 @@ +#ifndef _GAMEPAD_MANAGER_H_ +#define _GAMEPAD_MANAGER_H_ + +#include "TrackPlatform_Manager.h" + +class GamepadManager +{ + TrackPlatform_Manager* trackPlatform = nullptr; + bool * isNeedToExit = nullptr; +public: + GamepadManager(TrackPlatform_Manager* trackPlatform); + ~GamepadManager(); + void run(); +}; + +#endif /* _GAMEPAD_MANAGER_H_ */ diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln b/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln new file mode 100644 index 0000000..e6a8e0d --- /dev/null +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.16 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-gamepad-app", "cxx-gamepad-app.vcxproj", "{F92E7862-33C4-48B8-A055-3EE00352161F}" + ProjectSection(ProjectDependencies) = postProject + {32D3778A-E59E-4DBC-8D86-BD23B708CA12} = {32D3778A-E59E-4DBC-8D86-BD23B708CA12} + {4579D2EA-39EB-4766-9EB6-497500F379D6} = {4579D2EA-39EB-4766-9EB6-497500F379D6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-api", "..\cxx-api\cxx-api.vcxproj", "{32D3778A-E59E-4DBC-8D86-BD23B708CA12}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libstem_gamepad", "gamepad_support\msvc\libstem_gamepad\libstem_gamepad.vcxproj", "{4579D2EA-39EB-4766-9EB6-497500F379D6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x64.ActiveCfg = Debug|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x64.Build.0 = Debug|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x86.ActiveCfg = Debug|Win32 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Debug|x86.Build.0 = Debug|Win32 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x64.ActiveCfg = Release|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x64.Build.0 = Release|x64 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x86.ActiveCfg = Release|Win32 + {F92E7862-33C4-48B8-A055-3EE00352161F}.Release|x86.Build.0 = Release|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x64.ActiveCfg = Debug|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x64.Build.0 = Debug|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x86.ActiveCfg = Debug|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Debug|x86.Build.0 = Debug|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.ActiveCfg = Release|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.Build.0 = Release|x64 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.ActiveCfg = Release|Win32 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.Build.0 = Release|Win32 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Debug|x64.ActiveCfg = Debug|x64 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Debug|x64.Build.0 = Debug|x64 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Debug|x86.ActiveCfg = Debug|Win32 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Debug|x86.Build.0 = Debug|Win32 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x64.ActiveCfg = Release|x64 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x64.Build.0 = Release|x64 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x86.ActiveCfg = Release|Win32 + {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj new file mode 100644 index 0000000..59b5900 --- /dev/null +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {F92E7862-33C4-48B8-A055-3EE00352161F} + Win32Proj + cxxapp + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + true + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + false + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + false + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + + + Console + cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OutDir);$(SolutionDir)$(Configuration)\ + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + + + Console + cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OutDir);$(SolutionDir)$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + + + Console + true + true + cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OutDir);$(SolutionDir)$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + + + Console + true + true + cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(OutDir);$(SolutionDir)$(Platform)\$(Configuration)\ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters new file mode 100644 index 0000000..be33393 --- /dev/null +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp new file mode 100644 index 0000000..c5ee554 --- /dev/null +++ b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp @@ -0,0 +1,13 @@ +#include "gamepad_callbacks.h" + +void onButtonDown(Gamepad_device* device, unsigned buttonID, double timestamp, void* context) +{ +} + +void onButtonUp(Gamepad_device* device, unsigned buttonID, double timestamp, void* context) +{ +} + +void onAxisMoved(Gamepad_device* device, unsigned axisID, float value, float lastValue, double timestamp, void* context) +{ +} diff --git a/code/c++/cxx-gamepad-app/gamepad_callbacks.h b/code/c++/cxx-gamepad-app/gamepad_callbacks.h new file mode 100644 index 0000000..ba42f80 --- /dev/null +++ b/code/c++/cxx-gamepad-app/gamepad_callbacks.h @@ -0,0 +1,20 @@ +#ifndef _GAMEPAD_CALLBACKS_H_ +#define _GAMEPAD_CALLBACKS_H_ + +/** +* @brief Checks changes of buttons +* @param context Pointer to TrackPlatform_Manager variable. Used to call events +*/ +void onButtonDown(struct Gamepad_device * device, unsigned int buttonID, double timestamp, void * context); +/** + * @brief Checks is exit key was released + * @param context Pointer to bool variable. Sets to true, if exit key changed its pressing [pressed -> released], else sets false + */ +void onButtonUp(struct Gamepad_device * device, unsigned int buttonID, double timestamp, void * context); +/** +* @brief Checks changes of axes positions +* @param context Pointer to TrackPlatform_Manager variable. Used to call events +*/ +void onAxisMoved(struct Gamepad_device * device, unsigned int axisID, float value, float lastValue, double timestamp, void * context); + +#endif /* _GAMEPAD_CALLBACKS_H_ */ diff --git a/code/c++/cxx-gamepad-app/gamepad_support b/code/c++/cxx-gamepad-app/gamepad_support new file mode 160000 index 0000000..de3d4ca --- /dev/null +++ b/code/c++/cxx-gamepad-app/gamepad_support @@ -0,0 +1 @@ +Subproject commit de3d4ca0b9a6017b4ee8643287012a9a056521d5 diff --git a/code/c++/cxx-gamepad-app/main.cpp b/code/c++/cxx-gamepad-app/main.cpp new file mode 100644 index 0000000..888e70f --- /dev/null +++ b/code/c++/cxx-gamepad-app/main.cpp @@ -0,0 +1,29 @@ +#include +#include + +#include "GamepadManager.h" +#include "ConnectionModes.h" +#include "TrackPlatform_Manager.h" + +int main(int argc, char* argv[]) +{ + std::string rtx = "COM13"; + uint32_t baudrate = 9600U; + + std::cout << "rx = tx = " << rtx << "; baudrate = " << baudrate << std::endl; + + try + { + TrackPlatform_Manager trackPlatform(bluetooth, rtx, rtx, baudrate); + GamepadManager manager(&trackPlatform); + manager.run(); + } + catch(...) + { + std::cout << "Exception was catched" << std::endl; + return 1; + } + + return 0; +} + diff --git a/code/c++/cxx-gamepad-app/makefile b/code/c++/cxx-gamepad-app/makefile new file mode 100644 index 0000000..94336bc --- /dev/null +++ b/code/c++/cxx-gamepad-app/makefile @@ -0,0 +1,149 @@ +#Make file to compile source code for track platform cxx api library + +#Project Name +PROJECT_NAME = track-platform_cxx-gamepad-app +#Build option +BUILD ?= BUILD_STATIC +#ANSI Colos +ANSI_COLOR_RED = \e[31m +ANSI_COLOR_GREEN = \e[32m +ANSI_COLOR_YELLOW = \e[33m +ANSI_COLOR_BLUE = \e[34m +ANSI_COLOR_MAGENTA = \e[35m +ANSI_COLOR_CYAN = \e[36m +ANSI_COLOR_RESET = \e[37m +################################Compiller flags############################################################### +#Opitmization Level +OPT_LEVEL = -O0 +#Warning options +WARNINGS = -Wall -Wpedantic #-Werror +# WARNINGS += -fsyntax-only # for syntax checking only, without comlipation +WARNINGS_WITHOUT = +#User Compiller flags +USER_FLAGS ?= +############################################################################################################## +# OS redefinition +OS = $(shell uname -s) + +#Build patch +BUILD_PATH = Output/$(OS) +OBJ_PATH = $(BUILD_PATH)/obj + +#Compiller flags +CFLAGS = $(OPT_LEVEL) +CFLAGS += -g0 +CFLAGS += $(WARNINGS) +CFLAGS += -I. +CFLAGS += $(USER_FLAGS) +CFLAGS += -std=c++11 +CFLAGS += -D$(BUILD) +# ifeq ($(BUILD), BUILD_STATIC) +# CFLAGS += -D$(BUILD_STATIC) +# endif + +CFLAGS += $(INCLUDES) +############################################################################################################## +#Code file path +OTHER_PATH = . +OTHER_SOURCE_PATH = $(OTHER_PATH) +OTHER_INCLUDE_PATH = $(OTHER_PATH) + +#library path +API_PATH = ../cxx-api +API_INCLUDE_PATH = $(API_PATH) +API_BUILD_PATH = $(API_PATH)/$(BUILD_PATH) + +ifeq ($(BUILD), BUILD_STATIC) +API_NAME = track-platform_cxx-api.a +else +ifeq ($(BUILD), BUILD_DYNAMIC) +API_NAME = track-platform_cxx-api.so +endif +endif + +API_FULL_PATH = $(API_BUILD_PATH)/$(API_NAME) + +#Linker scrpit file +ARFLAGS = + +#Source file path + +SOURCES = +# Other code (non grouped) +SOURCES += $(OTHER_SOURCE_PATH)/main.cpp + +#Include file path +INCLUDES = +INCLUDES += -I$(API_INCLUDE_PATH) +# INCLUDES += -I$(OTHER_INCLUDE_PATH) + +############################################################################################################## +BUILD_PRINT = $(ANSI_COLOR_GREEN) Building:$(ANSI_COLOR_RESET) $@ +############################################################################################################## +#Output files +BIN = $(BUILD_PATH)/$(PROJECT_NAME) + +OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) + +STATIC_LIB: $(OBJECTS) api + @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) + @echo -e "$(BUILD_PRINT)" + +DYNAMIC_LIB: $(OBJECTS) api + $(error Dynamic library is not supported yet) + # @$(CXX) -shared -o $(BIN) $(OBJECTS) + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cc + @mkdir -p $(dir $@) + @$(CXX) -c $(CFLAGS) $< -o $@ + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cpp + @mkdir -p $(dir $@) + @$(CXX) -c $(CFLAGS) $< -o $@ + @echo -e "$(BUILD_PRINT)" + +#Makefile parameters +.DEFAULT_GOAL := all + +all: build + +ifeq ($(BUILD), BUILD_STATIC) +build: STATIC_LIB + +else +ifeq ($(BUILD), BUILD_DYNAMIC) +build: DYNAMIC_LIB + +else +build: + @echo "That BUILD variable is not supported. Use `make help` to see supported variants of build variable" +endif +endif + +dynamic: + $(MAKE) BUILD=BUILD_DYNAMIC + +static: + $(MAKE) BUILD=BUILD_STATIC + +api: + $(MAKE) -C $(API_PATH) BUILD=$(BUILD) + +clean: + @rm -rf $(BUILD_PATH) + $(MAKE) -C $(API_PATH) $@ + +run: + @$(BIN) + +set_def_color: + @echo -e "$(ANSI_COLOR_RESET)" + +help: + @echo "$(NEW_LINE)" + @echo "\tall : Builds static or dynamic library (static by default)" + @echo "\t\tIf you want to build static library(.a file), write `make` or `make static` or `make BUILD=BUILD_DYNAMIC`" + @echo "\t\tIf you want to build dynamic library(.so file), write `make dynamic` or `make BUILD=BUILD_DYNAMIC`" + @echo "$(NEW_LINE)" From a38622b76f1fc4d70ba4d64ac7e86a360cf34707 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 17 Aug 2017 10:35:41 +0300 Subject: [PATCH 049/336] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=BA=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B8=D0=B3?= =?UTF-8?q?=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 12 ++++++------ code/c++/cxx-gamepad-app/gamepad_support | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules index 47720d0..b712e71 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ -[submodule "cxx_serial_support"] - path = code/c++/cxx-api/serial_support - url = git@github.com:wjwwood/serial.git -[submodule "cxx_gamepad_support"] - path = code/c++/cxx-gamepad-app/gamepad_support - url = git@github.com:ThemsAllTook/libstem_gamepad.git +[submodule "cxx_serial_support"] + path = code/c++/cxx-api/serial_support + url = git@github.com:wjwwood/serial.git +[submodule "cxx_gamepad_support"] + path = code/c++/cxx-gamepad-app/gamepad_support +url=git@github.com:AJIOB/libstem_gamepad.git \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/gamepad_support b/code/c++/cxx-gamepad-app/gamepad_support index de3d4ca..7cd9720 160000 --- a/code/c++/cxx-gamepad-app/gamepad_support +++ b/code/c++/cxx-gamepad-app/gamepad_support @@ -1 +1 @@ -Subproject commit de3d4ca0b9a6017b4ee8643287012a9a056521d5 +Subproject commit 7cd97205f7acea05a208fcf833991e4e0b9f1cc6 From 9ef0036015169a7b9d247ba79695af034a1875a5 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 17 Aug 2017 19:48:38 +0300 Subject: [PATCH 050/336] =?UTF-8?q?=D0=92=D1=81=D0=B5=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BC=D1=83=D0=BD=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D1=8B=20=D0=BD?= =?UTF-8?q?=D0=B0=20HardwareSerial=20(=D0=B7=D0=B0=20=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 24 ++++++++++++------------ code/Arduino/Constants.h | 8 ++++---- code/Arduino/connectors/Bluetooth.cpp | 10 ++++++++-- code/Arduino/connectors/Bluetooth.h | 11 ++++++++++- code/Arduino/connectors/DebugSerial.cpp | 2 +- code/Arduino/connectors/DebugSerial.h | 2 +- code/Arduino/connectors/WiFi.cpp | 13 +++++++++++-- code/Arduino/connectors/WiFi.h | 7 ++++++- code/Arduino/trackPlatform.ino | 20 +++++++++++--------- 9 files changed, 64 insertions(+), 33 deletions(-) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index a06604b..302008c 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -1,21 +1,21 @@ #include "Constants.h" -/* Bluetooth */ -const uint8_t Constants::bluetooth_RX = 50; -const uint8_t Constants::bluetooth_TX = 51; +/* Bluetooth (Hardware Serial3) */ +// const uint8_t Constants::bluetooth_RX = 15; +// const uint8_t Constants::bluetooth_TX = 14; const uint32_t Constants::bluetooth_serial_speed = 9600; -/* Wi-fi */ -const uint8_t Constants::wifi_RX = 30; -const uint8_t Constants::wifi_TX = 31; -const uint32_t Constants::wifi_serial_speed = 9600; +/* Wi-fi (Hardware Serial2) */ +// const uint8_t Constants::wifi_RX = 17; +// const uint8_t Constants::wifi_TX = 16; +const uint32_t Constants::wifi_serial_speed = 115200; -/* USB */ +/* USB (Hardware Serial) */ // const uint8_t Constants::usb_RX = 0; // const uint8_t Constants::usb_TX = 1; const uint32_t Constants::usb_serial_speed = 9600; -/* Debug serial */ +/* Debug serial (Hardware Serial1 maybe will be in future) */ const uint8_t Constants::dbg_uart_RX = 52; const uint8_t Constants::dbg_uart_TX = 53; const uint32_t Constants::dbg_uart_speed = 9600; @@ -36,9 +36,9 @@ const uint8_t Constants::distance_sensor_c_pin = 6; /* Line controller */ const uint8_t Constants::line_sensor_read_pin = A1; -const uint8_t Constants::line_sensor_a_pin = 15; -const uint8_t Constants::line_sensor_b_pin = 16; -const uint8_t Constants::line_sensor_c_pin = 17; +const uint8_t Constants::line_sensor_a_pin = 8; +const uint8_t Constants::line_sensor_b_pin = 9; +const uint8_t Constants::line_sensor_c_pin = 10; /* Servo controller */ const uint8_t Constants::servo_horizontal_pin = 34; diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index 851a78f..47ea8b2 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -4,12 +4,12 @@ class Constants { public: - static const uint8_t bluetooth_RX; - static const uint8_t bluetooth_TX; + // static const uint8_t bluetooth_RX; + // static const uint8_t bluetooth_TX; static const uint32_t bluetooth_serial_speed; - static const uint8_t wifi_RX; - static const uint8_t wifi_TX; + // static const uint8_t wifi_RX; + // static const uint8_t wifi_TX; static const uint32_t wifi_serial_speed; // static const uint8_t usb_RX; diff --git a/code/Arduino/connectors/Bluetooth.cpp b/code/Arduino/connectors/Bluetooth.cpp index 1dc2bed..98c3429 100644 --- a/code/Arduino/connectors/Bluetooth.cpp +++ b/code/Arduino/connectors/Bluetooth.cpp @@ -1,11 +1,17 @@ +#include "../Constants.h" #include "Bluetooth.h" +bool Bluetooth::isInited = false; -Bluetooth::Bluetooth(int rx, int tx, int speed) : ConnectingDevice(rx, tx, speed) +Bluetooth::Bluetooth() : ConnectingDevice(&Serial3) { + if (!isInited) + { + isInited = true; + Serial3.begin(Constants::bluetooth_serial_speed); + } } - Bluetooth::~Bluetooth() { } diff --git a/code/Arduino/connectors/Bluetooth.h b/code/Arduino/connectors/Bluetooth.h index 38ff722..67d0964 100644 --- a/code/Arduino/connectors/Bluetooth.h +++ b/code/Arduino/connectors/Bluetooth.h @@ -1,10 +1,19 @@ #pragma once #include "ConnectingDevice.h" +/** + * @brief Bluetooth controller class + * @attention Create first object of that class in setup() method only + */ class Bluetooth : public ConnectingDevice { + /** + * @brief Block for double initialization + */ + static bool isInited; + public: - Bluetooth(int rx, int tx, int speed); + Bluetooth(); ~Bluetooth(); }; diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp index eafc714..3686a22 100644 --- a/code/Arduino/connectors/DebugSerial.cpp +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -4,7 +4,7 @@ #ifdef DEBUG_ON -SoftwareSerial* DebugSerial::serial = DebugSerial::generateDbgSerial(); +HardwareSerial* DebugSerial::serial = &Serial1; SoftwareSerial* DebugSerial::generateDbgSerial() { diff --git a/code/Arduino/connectors/DebugSerial.h b/code/Arduino/connectors/DebugSerial.h index 6261754..0e8b434 100644 --- a/code/Arduino/connectors/DebugSerial.h +++ b/code/Arduino/connectors/DebugSerial.h @@ -29,7 +29,7 @@ #ifdef DEBUG_ON class DebugSerial : public ConnectingDevice { - static SoftwareSerial* serial; + static HardwareSerial* serial; static const int printfBuffSize = 120; static SoftwareSerial* generateDbgSerial(); diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index f7874f1..1f543d7 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -1,9 +1,18 @@ +#include "../Constants.h" #include "WiFi.h" +bool WiFi::isInited = false; - -WiFi::WiFi(int rx, int tx, int speed) : ConnectingDevice(rx, tx, speed) +WiFi::WiFi(int speed) : ConnectingDevice(&Serial2) { + if (isInited) + { + return; + } + + isInited = true; + Serial2.begin(Constants::wifi_serial_speed); + if (Check()) { ChangeSpeed(speed); diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 26c89f8..7116d6d 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -3,8 +3,13 @@ class WiFi : public ConnectingDevice { + /** + * @brief Block for double initialization + */ + static bool isInited; + public: - WiFi(int rx, int tx, int speed); + WiFi(int speed); ~WiFi(); /** diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index d3eabf3..3edf025 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -18,9 +18,9 @@ void off45(); #endif /* DIOD_DEBUG */ Constants constants; -Bluetooth bluetooth(constants.bluetooth_RX, constants.bluetooth_TX, constants.bluetooth_serial_speed); -WiFi wifi(constants.wifi_RX, constants.wifi_TX, constants.wifi_serial_speed); -USB* usb; +Bluetooth* bluetooth = nullptr; +WiFi* wifi = nullptr; +USB* usb = nullptr; ConnectingDevice *device = nullptr; CommandsController* controller; @@ -32,19 +32,21 @@ void setup() DEBUG_PRINTLN("Arduino was started"); - usb = new USB(); + usb = new USB(); + wifi = new WiFi(Constants::wifi_serial_speed); + bluetooth = new Bluetooth(); controller = new CommandsController(); bool connected = false; while (!connected) { - if (bluetooth.isActive()) { + if (bluetooth->isActive()) { connected = true; - device = &bluetooth; + device = bluetooth; DEBUG_PRINTLN("Bluetooth"); } - else if (wifi.isActive()) { + else if (wifi->isActive()) { connected = true; - device = &wifi; + device = wifi; DEBUG_PRINTLN("Wifi"); } else if (usb->isActive()) { @@ -61,7 +63,7 @@ void loop() { String command = device->read(); - //debug + //debug DEBUG_PRINT("Command: "); DEBUG_PRINTLNHEX(command); From dafb3d9910c1b3b1d5281046645583ddef01992b Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 17 Aug 2017 19:57:11 +0300 Subject: [PATCH 051/336] =?UTF-8?q?=D0=A1=D0=BA=D0=BE=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=B5=D1=8E=D1=82=20=D1=82=D0=B8=D0=BF=20unsigned=20log?= =?UTF-8?q?=20(=D0=B8=D0=BB=D0=B8=20uint32=5Ft).=20=D0=92=D1=81=D0=B5=20?= =?UTF-8?q?=D1=83=D1=81=D1=82=D1=80=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D1=8E=D1=82=20=D1=81=D0=B2=D0=BE?= =?UTF-8?q?=D0=B8=20=D1=81=D0=BA=D0=BE=D1=80=D0=BE=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/Bluetooth.cpp | 5 ++--- code/Arduino/connectors/Bluetooth.h | 2 +- code/Arduino/connectors/ConnectingDevice.cpp | 2 +- code/Arduino/connectors/ConnectingDevice.h | 2 +- code/Arduino/connectors/USB.cpp | 11 +++++++---- code/Arduino/connectors/USB.h | 3 ++- code/Arduino/connectors/WiFi.cpp | 9 ++++----- code/Arduino/connectors/WiFi.h | 6 +++--- code/Arduino/trackPlatform.ino | 4 ++-- 9 files changed, 23 insertions(+), 21 deletions(-) diff --git a/code/Arduino/connectors/Bluetooth.cpp b/code/Arduino/connectors/Bluetooth.cpp index 98c3429..b2bce7c 100644 --- a/code/Arduino/connectors/Bluetooth.cpp +++ b/code/Arduino/connectors/Bluetooth.cpp @@ -1,14 +1,13 @@ -#include "../Constants.h" #include "Bluetooth.h" bool Bluetooth::isInited = false; -Bluetooth::Bluetooth() : ConnectingDevice(&Serial3) +Bluetooth::Bluetooth(unsigned long speed) : ConnectingDevice(&Serial3) { if (!isInited) { isInited = true; - Serial3.begin(Constants::bluetooth_serial_speed); + Serial3.begin(speed); } } diff --git a/code/Arduino/connectors/Bluetooth.h b/code/Arduino/connectors/Bluetooth.h index 67d0964..fd376b2 100644 --- a/code/Arduino/connectors/Bluetooth.h +++ b/code/Arduino/connectors/Bluetooth.h @@ -13,7 +13,7 @@ class Bluetooth : public ConnectingDevice static bool isInited; public: - Bluetooth(); + explicit Bluetooth(unsigned long speed); ~Bluetooth(); }; diff --git a/code/Arduino/connectors/ConnectingDevice.cpp b/code/Arduino/connectors/ConnectingDevice.cpp index 4b94ea4..c6e9034 100644 --- a/code/Arduino/connectors/ConnectingDevice.cpp +++ b/code/Arduino/connectors/ConnectingDevice.cpp @@ -7,7 +7,7 @@ ConnectingDevice::ConnectingDevice(Stream* ptr) : device(ptr) device->setTimeout(Constants::commands_waitTime); } -ConnectingDevice::ConnectingDevice(int rx, int tx, int speed) +ConnectingDevice::ConnectingDevice(int rx, int tx, unsigned long speed) { SoftwareSerial* serialPtr = new SoftwareSerial(rx, tx); serialPtr->begin(speed); diff --git a/code/Arduino/connectors/ConnectingDevice.h b/code/Arduino/connectors/ConnectingDevice.h index a5752e6..38efb69 100644 --- a/code/Arduino/connectors/ConnectingDevice.h +++ b/code/Arduino/connectors/ConnectingDevice.h @@ -9,7 +9,7 @@ class ConnectingDevice Stream *device; public: - ConnectingDevice(int rx, int tx, int speed); + ConnectingDevice(int rx, int tx, unsigned long speed); virtual bool isActive(); virtual String read(); virtual void send(String data); diff --git a/code/Arduino/connectors/USB.cpp b/code/Arduino/connectors/USB.cpp index beb312a..161516a 100644 --- a/code/Arduino/connectors/USB.cpp +++ b/code/Arduino/connectors/USB.cpp @@ -1,13 +1,16 @@ -#include "../Constants.h" -#include "USB.h" +#include "USB.h" bool USB::isInited = false; -USB::USB() : ConnectingDevice(&Serial) +USB::USB(unsigned long speed) : ConnectingDevice(&Serial) { if (!isInited) { isInited = true; - Serial.begin(Constants::usb_serial_speed); + Serial.begin(speed); } } + +USB::~USB() +{ +} diff --git a/code/Arduino/connectors/USB.h b/code/Arduino/connectors/USB.h index 7c124ce..5b9ac12 100644 --- a/code/Arduino/connectors/USB.h +++ b/code/Arduino/connectors/USB.h @@ -14,5 +14,6 @@ class USB : public ConnectingDevice static bool isInited; public: - USB(); + explicit USB(unsigned long speed); + ~USB(); }; diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index 1f543d7..fe1fa1c 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -1,9 +1,8 @@ -#include "../Constants.h" #include "WiFi.h" bool WiFi::isInited = false; -WiFi::WiFi(int speed) : ConnectingDevice(&Serial2) +WiFi::WiFi(unsigned long speed) : ConnectingDevice(&Serial2) { if (isInited) { @@ -11,7 +10,7 @@ WiFi::WiFi(int speed) : ConnectingDevice(&Serial2) } isInited = true; - Serial2.begin(Constants::wifi_serial_speed); + Serial2.begin(speed); if (Check()) { @@ -39,7 +38,7 @@ String WiFi::CheckIPandMAC() return read(); } -void WiFi::ChangeSpeed(int speed) +void WiFi::ChangeSpeed(unsigned long speed) { if (ready) { @@ -54,7 +53,7 @@ bool WiFi::Reset() return ready; } -bool WiFi::Reset(int speed) +bool WiFi::Reset(unsigned long speed) { ready = Reset(); ChangeSpeed(speed); diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 7116d6d..6576984 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -9,7 +9,7 @@ class WiFi : public ConnectingDevice static bool isInited; public: - WiFi(int speed); + explicit WiFi(unsigned long speed); ~WiFi(); /** @@ -35,7 +35,7 @@ class WiFi : public ConnectingDevice * @param speed . , , - . , */ - virtual void ChangeSpeed(int speed); + virtual void ChangeSpeed(unsigned long speed); /** * @@ -48,7 +48,7 @@ class WiFi : public ConnectingDevice * * String */ - virtual bool Reset(int speed); + virtual bool Reset(unsigned long speed); /** * diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 3edf025..4ab0ead 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -32,9 +32,9 @@ void setup() DEBUG_PRINTLN("Arduino was started"); - usb = new USB(); + usb = new USB(Constants::usb_serial_speed); wifi = new WiFi(Constants::wifi_serial_speed); - bluetooth = new Bluetooth(); + bluetooth = new Bluetooth(Constants::bluetooth_serial_speed); controller = new CommandsController(); bool connected = false; From 6359701973893b3a0cc7ac453faa700035a2c7cf Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Thu, 17 Aug 2017 23:49:43 +0300 Subject: [PATCH 052/336] =?UTF-8?q?=D0=97=D0=B0=D0=BA=D0=BE=D0=BD=D1=87?= =?UTF-8?q?=D0=B8=D0=BB=20Wi-Fi=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 190 +++++++++++++++++++++++++------ code/Arduino/connectors/WiFi.h | 80 ++++++++----- 2 files changed, 206 insertions(+), 64 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index f7874f1..9644ca8 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -1,7 +1,5 @@ #include "WiFi.h" - - WiFi::WiFi(int rx, int tx, int speed) : ConnectingDevice(rx, tx, speed) { if (Check()) @@ -18,31 +16,71 @@ WiFi::~WiFi() { } +bool WiFi::ReturningCommandsOff() +{ + try + { + send("ATE0"); + } + catch (...) + { + return false; + } + return true; +} + String WiFi::VersionCheck() { - send("AT+GMR"); - return read(); + try + { + send("AT+GMR"); + return ReturnInfo(); + } + catch (...) + { + return ""; + } } String WiFi::CheckIPandMAC() { - send("AT+CIFSR"); - return read(); + try + { + send("AT+CIFSR"); + ReturnCheck(); + return ReturnInfo(); + } + catch (...) + { + return ""; + } } -void WiFi::ChangeSpeed(int speed) +bool WiFi::ChangeSpeed(int speed) { - if (ready) + try { send("AT+CIOBAUD=" + String(speed)); + ReturnCheck(); + } + catch (...) + { + return false; } + return true; } bool WiFi::Reset() { send("AT+RST"); - ready = (read() == "OK"); - return ready; + if (ready = (read() == "AT+RST\r\nOK") == ReturningCommandsOff()) + { + return ready; + } + else + { + return; + } } bool WiFi::Reset(int speed) @@ -52,71 +90,151 @@ bool WiFi::Reset(int speed) return ready; } -void WiFi::CreateCurrentHost(String name, String password, int port) +bool WiFi::CreateCurrentHost(String name, String password, int port) { - if (ready) + try { - if (!opened) - { - Open(); - } + Open(); + ReturnCheck(); send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); + ReturnCheck(); UseTCP(port); } + catch (...) + { + return false; + } + return true; } -void WiFi::CreateStaticHost(String name, String password, int port) +bool WiFi::CreateStaticHost(String name, String password, int port) { - if (ready) + try { - if (!opened) - { - Open(); - } + Open(); + ReturnCheck(); send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); + ReturnCheck(); UseTCP(port); } + catch (...) + { + return false; + } + return true; } String WiFi::NetsList() { - if (ready) + try { if (opened) { Close(); } send("AT+CWLAP"); - return read(); + return ReturnInfo(); + } + catch (...) + { + return ""; } } -void WiFi::Close() +bool WiFi::Close() { - send("AT+CWMODE_CUR=1"); - opened = false; + try + { + send("AT+CWMODE_CUR=1"); + ReturnCheck(); + opened = false; + } + catch (...) + { + return false; + } + return true; } -void WiFi::Open() +bool WiFi::Open() { - send("AT+CWMODE_CUR=2"); - opened = true; + try + { + send("AT+CWMODE_CUR=2"); + ReturnCheck(); + opened = true; + } + catch (...) + { + return false; + } + return true; } -void WiFi::UseTCP(int port) +bool WiFi::UseTCP(int port) { - send("AT+CIPMUX=1"); - send("AT+CIPSERVER=1," + String(port)); + try + { + send("AT+CIPMUX=1"); + ReturnCheck(); + send("AT+CIPSERVER=1," + String(port)); + ReturnCheck(); + } + catch (...) + { + return false; + } + return true; } bool WiFi::Check() { send("AT"); - ready = (read() == "OK"); - return ready; + if (ready = (read() == "AT\r\nOK") == ReturningCommandsOff()) + { + return ready; + } + else + { + Reset(); + } +} + +void WiFi::ReturnCheck() +{ + if (read() != "\r\nOK") + { + throw 1; + } +} + +String WiFi::ReturnInfo() +{ + String str = read(); + if (int a = str.indexOf("\r\nOK")) + { + return str.substring(0, a); + } + else + { + throw 1; + } } void WiFi::send(String command) { - ConnectingDevice::send(command + "\r\n"); + if (ready) + { + ConnectingDevice::send(command + "\r\n"); + } + else + { + throw 1; + } +} + +String WiFi::read() +{ + delay(100); + return ConnectingDevice::read(); } \ No newline at end of file diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 26c89f8..85cbc0a 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -7,89 +7,113 @@ class WiFi : public ConnectingDevice WiFi(int rx, int tx, int speed); ~WiFi(); + /** + * @brief + */ + virtual bool ReturningCommandsOff(); + /** * @brief - * @return String + * @return */ virtual String VersionCheck(); /** * @brief - * @ String + * @return */ virtual String NetsList(); /** * @brief IP MAC - * @ String + * @return IP MAC */ virtual String CheckIPandMAC(); /** - * @ + * @brief * @param speed - . , , - . , */ - virtual void ChangeSpeed(int speed); + virtual bool ChangeSpeed(int speed); /** - * - * String + * @brief + * @return */ virtual bool Reset(); /** - * - * - * String + * @brief + * @param speed + * @return */ virtual bool Reset(int speed); /** - * - * bool + * @brief + * @return + */ + virtual void ReturnCheck(); + + /** + * @brief + * @return */ virtual bool Check(); /** - * + * @brief */ - virtual void Close(); + virtual bool Close(); /** - * TCP + * @brief TCP */ - virtual void Open(); + virtual bool Open(); /** - * TCP - * int + * @brief TCP + * @param */ - virtual void UseTCP(int port); + virtual bool UseTCP(int port); /** - * - * String, String int UseTCP + * @brief + * @param name , password port UseTCP */ - virtual void CreateCurrentHost(String name, String password, int port); + virtual bool CreateCurrentHost(String name, String password, int port); /** - * - * String, String int UseTCP + * @brief + * @param name , password port UseTCP */ - virtual void CreateStaticHost(String name, String password, int port); + virtual bool CreateStaticHost(String name, String password, int port); + /** + * @brief , "\r\n" + */ void send(String command) override; + /** + * @brief , + */ + String read() override; + + /** + * @brief + * @return + */ + virtual String ReturnInfo(); + private: /** - * + * @brief */ bool ready = false; /** - * / + * @brief / */ bool opened = false; }; \ No newline at end of file From 0c58a0a21232a8fa2d8271917ac6164973e515bd Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 00:09:25 +0300 Subject: [PATCH 053/336] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B1=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D1=8F=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0=D0=B4=D0=B0=20?= =?UTF-8?q?=D0=B8=20=D1=81=D0=BF=D0=BE=D1=81=D0=BE=D0=B1=D1=8B=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20=D0=BD=D0=B5=D0=B9=20?= =?UTF-8?q?(=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D1=82=D0=B5=D0=BA=D1=83=D1=89=D0=B5=D0=B3=D0=BE=20=D0=B7=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=84?= =?UTF-8?q?=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86=D0=B8=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadConfig.cpp | 38 ++++++++++++++++++++++ code/c++/cxx-gamepad-app/GamepadConfig.h | 32 ++++++++++++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.cpp b/code/c++/cxx-gamepad-app/GamepadConfig.cpp index afcadc1..fff1cdb 100644 --- a/code/c++/cxx-gamepad-app/GamepadConfig.cpp +++ b/code/c++/cxx-gamepad-app/GamepadConfig.cpp @@ -1 +1,39 @@ #include "GamepadConfig.h" + +GamepadConfig::GamepadConfig() : + buttonsBinding { + GamepadCommands::distanceSensorRefresh, /* 1 - A */ + GamepadCommands::exit, /* 2 - B */ + GamepadCommands::lineSensorRefresh, /* 3 - X */ + GamepadCommands::none, /* 4 - Y */ + GamepadCommands::none, /* 5 */ + GamepadCommands::none, /* 6 */ + GamepadCommands::none, /* 7 */ + GamepadCommands::none, /* 8 */ + GamepadCommands::none, /* 9 */ + GamepadCommands::none, /* 10 */ + GamepadCommands::none, /* 11 */ + GamepadCommands::none, /* 12 */ + GamepadCommands::none, /* 13 */ + GamepadCommands::none, /* 14 */ + }, + sticksBinding { + GamepadCommands::moveRobotX, /* 1 - left X */ + GamepadCommands::moveRobotY, /* 2 - left Y */ + GamepadCommands::moveCameraX, /* 3 - right X */ + GamepadCommands::moveCameraY, /* 4 - right Y */ + GamepadCommands::none, /* 5 */ + GamepadCommands::none, /* 6 */ + } +{ +} + +GamepadCommands GamepadConfig::button(int index) const +{ + return ((index >= 0) && (index < maxButtons)) ? buttonsBinding[index] : GamepadCommands::none; +} + +GamepadCommands GamepadConfig::stick(int index) const +{ + return ((index >= 0) && (index < maxSticks)) ? sticksBinding[index] : GamepadCommands::none; +} diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.h b/code/c++/cxx-gamepad-app/GamepadConfig.h index 7141864..760ba0b 100644 --- a/code/c++/cxx-gamepad-app/GamepadConfig.h +++ b/code/c++/cxx-gamepad-app/GamepadConfig.h @@ -1,14 +1,42 @@ #ifndef _GAMEPAD_CONFIG_H_ #define _GAMEPAD_CONFIG_H_ -typedef enum +enum class GamepadCommands { + none, + + /* App management */ + exit, + + /* Movement */ + moveRobotX, + moveRobotY, + moveCameraX, + moveCameraY, -} GamepadCommands; + /* Sensors */ + lineSensorRefresh, + distanceSensorRefresh, +}; class GamepadConfig { + static const short int maxButtons = 14; + static const short int maxSticks = 6; + + GamepadCommands buttonsBinding[maxButtons]; + GamepadCommands sticksBinding[maxSticks]; public: + GamepadConfig(); + + /** + * @return Button mapping command or @GamepadCommands::none, if not exists + */ + GamepadCommands button(int index) const; + /** + * @return Button mapping command or @GamepadCommands::none, if not exists + */ + GamepadCommands stick(int index) const; }; #endif /* _GAMEPAD_CONFIG_H_ */ From 7c67ce0063899efda5e9f305490769bcb4715f25 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 11:10:11 +0300 Subject: [PATCH 054/336] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=D0=B6=D0=BA=D0=B0=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadConfig.cpp | 8 +- code/c++/cxx-gamepad-app/GamepadManager.cpp | 144 +++++------------- code/c++/cxx-gamepad-app/GamepadManager.h | 35 ++++- .../c++/cxx-gamepad-app/gamepad_callbacks.cpp | 28 +++- code/c++/cxx-gamepad-app/gamepad_callbacks.h | 8 +- 5 files changed, 112 insertions(+), 111 deletions(-) diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.cpp b/code/c++/cxx-gamepad-app/GamepadConfig.cpp index fff1cdb..6230e86 100644 --- a/code/c++/cxx-gamepad-app/GamepadConfig.cpp +++ b/code/c++/cxx-gamepad-app/GamepadConfig.cpp @@ -11,10 +11,10 @@ GamepadConfig::GamepadConfig() : GamepadCommands::none, /* 7 */ GamepadCommands::none, /* 8 */ GamepadCommands::none, /* 9 */ - GamepadCommands::none, /* 10 */ - GamepadCommands::none, /* 11 */ - GamepadCommands::none, /* 12 */ - GamepadCommands::none, /* 13 */ + GamepadCommands::distanceSensorRefresh, /* 10 - 3 on defender */ + GamepadCommands::lineSensorRefresh, /* 11 - 2 on defender */ + GamepadCommands::exit, /* 12 - 4 on defender */ + GamepadCommands::none, /* 13 - 1 on defender */ GamepadCommands::none, /* 14 */ }, sticksBinding { diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp index 913242d..7a92f85 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.cpp +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -4,121 +4,61 @@ #include "GamepadManager.h" -GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), isNeedToExit(new bool(false)) +GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), isRunningNow(new std::mutex), runnedThread(nullptr) { - Gamepad_buttonDownFunc(onButtonDown, (void *)trackPlatform); - Gamepad_buttonUpFunc(onButtonUp, (void *)isNeedToExit); - Gamepad_axisMoveFunc(onAxisMoved, (void *)trackPlatform); + Gamepad_buttonDownFunc(onButtonDown, (void *)this); + Gamepad_buttonUpFunc(onButtonUp, (void *)this); + Gamepad_axisMoveFunc(onAxisMoved, (void *)this); Gamepad_init(); } GamepadManager::~GamepadManager() { - if (isNeedToExit) + stop(); + join(); + if (isRunningNow) { - delete isNeedToExit; + delete isRunningNow; + } + if (runnedThread) + { + delete runnedThread; } Gamepad_shutdown(); } void GamepadManager::run() { - Gamepad_detectDevices(); - Gamepad_processEvents(); + runnedThread = runnedThread ? runnedThread : new std::thread([this]() + { + while (this->isRunningNow && !this->isRunningNow->try_lock()) + { + Gamepad_detectDevices(); + Gamepad_processEvents(); + } + + this->isRunningNow->unlock(); + }); +} + +void GamepadManager::stop() +{ + //TODO +} + +void GamepadManager::join() +{ + //TODO +} + +const GamepadConfig& GamepadManager::getConfig() const +{ + return config; +} - //bool isExit = false; - //while (!isExit) - //{ - // //std::cout << "Input command, please (0 to help): "; - // auto c = 0; - // //std::cout << std::endl; +TrackPlatform_Manager* GamepadManager::getTrackPlatformManager() const +{ + return trackPlatform; +} - // switch (c) - // { - // case '0': - // //std::cout << "0: help" << std::endl; - // //std::cout << "q: quit" << std::endl; - // //std::cout << "w: move forward" << std::endl; - // //std::cout << "s: move back" << std::endl; - // //std::cout << "a: turn left (anticlockwise)" << std::endl; - // //std::cout << "d: turn right (clockwise)" << std::endl; - // //std::cout << " : stop" << std::endl; - // //std::cout << "r: get all line values" << std::endl; - // //std::cout << "e: get fixed line value" << std::endl; - // //std::cout << "t: get all distance values" << std::endl; - // //std::cout << "y: get fixed distance value" << std::endl; - // //std::cout << "g: set horisontal servo angle in degree" << std::endl; - // //std::cout << "h: set vertical servo angle in degree" << std::endl; - // break; - // case 'q': - // isExit = true; - // break; - // case 'w': - // trackPlatform.moveForward(); - // break; - // case 'a': - // trackPlatform.moveBackward(); - // break; - // case 's': - // trackPlatform.rotateAntiClockwise(); - // break; - // case 'd': - // trackPlatform.rotateClockwise(); - // break; - // case ' ': - // trackPlatform.moveStopAll(); - // break; - // case 'r': - // { - // auto arr = trackPlatform.sensorLineGetAllValues(); - // for (auto a : arr) - // { - // //std::cout << a << std::endl; - // } - // break; - // } - // case 'e': - // { - // //std::cout << "Input num: "; - // int a; - // //std::cin >> a; - // //std::cout << "Value: " << trackPlatform.sensorLineGetValue(a) << std::endl; - // break; - // } - // case 't': - // { - // auto arr = trackPlatform.sensorDistanceGetAllValues(); - // for (auto a : arr) - // { - // //std::cout << a << std::endl; - // } - // break; - // } - // case 'y': - // { - // //std::cout << "Input num: "; - // int a; - // //std::cin >> a; - // //std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a) << std::endl; - // break; - // } - // case 'g': - // { - // //std::cout << "Input num: "; - // int a; - // //std::cin >> a; - // trackPlatform.servoSetHorizontalAngle(a); - // break; - // } - // case 'h': - // { - // //std::cout << "Input num: "; - // int a; - // //std::cin >> a; - // trackPlatform.servoSetVerticalAngle(a); - // break; - // } - // default: break; - // } - //} } diff --git a/code/c++/cxx-gamepad-app/GamepadManager.h b/code/c++/cxx-gamepad-app/GamepadManager.h index a2dfe41..ab40fe3 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.h +++ b/code/c++/cxx-gamepad-app/GamepadManager.h @@ -1,16 +1,49 @@ #ifndef _GAMEPAD_MANAGER_H_ #define _GAMEPAD_MANAGER_H_ +#include #include "TrackPlatform_Manager.h" +#include "GamepadConfig.h" class GamepadManager { TrackPlatform_Manager* trackPlatform = nullptr; - bool * isNeedToExit = nullptr; + /** + * @brief mutex is locked when handler thread is running, else not locked + */ + std::mutex * isRunningNow = nullptr; + /** + * @brief Handler thread pointer + */ + std::thread * runnedThread = nullptr; + + GamepadConfig config; + public: GamepadManager(TrackPlatform_Manager* trackPlatform); ~GamepadManager(); + /** + * @brief Run gamepad handler thread + */ void run(); + /** + * @brief Stop gamepad handler thread + */ + void stop(); + /** + * @brief Wait while handler thread not stopped + */ + void join(); + /** + * @brief Get current gamepad config + * @return Current gamepad configuration + */ + const GamepadConfig& getConfig() const; + /** + * @brief Get current trackPlatform manager + * @return Current trackPlatform manager + */ + TrackPlatform_Manager* getTrackPlatformManager() const; }; #endif /* _GAMEPAD_MANAGER_H_ */ diff --git a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp index c5ee554..c2c373b 100644 --- a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp +++ b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp @@ -1,7 +1,27 @@ -#include "gamepad_callbacks.h" +#include "GamepadManager.h" +#include "gamepad_callbacks.h" void onButtonDown(Gamepad_device* device, unsigned buttonID, double timestamp, void* context) { + GamepadManager* manager = static_cast(context); + switch (manager->getConfig().button(buttonID)) + { + case GamepadCommands::exit: { + manager->stop(); + break; + } + case GamepadCommands::lineSensorRefresh: { + auto values = manager->getTrackPlatformManager()->sensorLineGetAllValues(); + //TODO: show on screen + break; + } + case GamepadCommands::distanceSensorRefresh: { + auto values = manager->getTrackPlatformManager()->sensorDistanceGetAllValues(); + //TODO: show on screen + break; + } + default: break; + } } void onButtonUp(Gamepad_device* device, unsigned buttonID, double timestamp, void* context) @@ -10,4 +30,10 @@ void onButtonUp(Gamepad_device* device, unsigned buttonID, double timestamp, voi void onAxisMoved(Gamepad_device* device, unsigned axisID, float value, float lastValue, double timestamp, void* context) { + GamepadManager* manager = static_cast(context); + switch (manager->getConfig().stick(axisID)) + { + //TODO: process sticks + default: break; + } } diff --git a/code/c++/cxx-gamepad-app/gamepad_callbacks.h b/code/c++/cxx-gamepad-app/gamepad_callbacks.h index ba42f80..ccd09fb 100644 --- a/code/c++/cxx-gamepad-app/gamepad_callbacks.h +++ b/code/c++/cxx-gamepad-app/gamepad_callbacks.h @@ -1,19 +1,21 @@ #ifndef _GAMEPAD_CALLBACKS_H_ #define _GAMEPAD_CALLBACKS_H_ +#include "gamepad/Gamepad.h" + /** * @brief Checks changes of buttons -* @param context Pointer to TrackPlatform_Manager variable. Used to call events +* @param context Pointer to @GamepadManager variable. Used to call events */ void onButtonDown(struct Gamepad_device * device, unsigned int buttonID, double timestamp, void * context); /** * @brief Checks is exit key was released - * @param context Pointer to bool variable. Sets to true, if exit key changed its pressing [pressed -> released], else sets false + * @param context Pointer to @GamepadManager variable. Sets to true, if exit key changed its pressing [pressed -> released], else sets false */ void onButtonUp(struct Gamepad_device * device, unsigned int buttonID, double timestamp, void * context); /** * @brief Checks changes of axes positions -* @param context Pointer to TrackPlatform_Manager variable. Used to call events +* @param context Pointer to @GamepadManager variable. Used to call events */ void onAxisMoved(struct Gamepad_device * device, unsigned int axisID, float value, float lastValue, double timestamp, void * context); From a2e9826cb58100f24611ffe6bf3d9867b09c37c2 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 13:03:54 +0300 Subject: [PATCH 055/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BA=D0=BE=D0=B2=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?.=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B0=20=D0=B2?= =?UTF-8?q?=D0=BD=D1=83=D1=82=D1=80=D0=B5=D0=BD=D0=BD=D1=8F=D1=8F=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B2?= =?UTF-8?q?=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B4=D0=B5=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B8=D1=8F=20=D1=81=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20GamepadManager.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadConfig.cpp | 25 +++++++--- code/c++/cxx-gamepad-app/GamepadConfig.h | 8 ++++ code/c++/cxx-gamepad-app/GamepadManager.cpp | 46 +++++++++++++++---- code/c++/cxx-gamepad-app/GamepadManager.h | 14 +++++- .../c++/cxx-gamepad-app/gamepad_callbacks.cpp | 15 +++++- code/c++/cxx-gamepad-app/main.cpp | 1 + 6 files changed, 90 insertions(+), 19 deletions(-) diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.cpp b/code/c++/cxx-gamepad-app/GamepadConfig.cpp index 6230e86..ee66f96 100644 --- a/code/c++/cxx-gamepad-app/GamepadConfig.cpp +++ b/code/c++/cxx-gamepad-app/GamepadConfig.cpp @@ -2,6 +2,7 @@ GamepadConfig::GamepadConfig() : buttonsBinding { + GamepadCommands::none, /* 0 */ GamepadCommands::distanceSensorRefresh, /* 1 - A */ GamepadCommands::exit, /* 2 - B */ GamepadCommands::lineSensorRefresh, /* 3 - X */ @@ -15,15 +16,14 @@ GamepadConfig::GamepadConfig() : GamepadCommands::lineSensorRefresh, /* 11 - 2 on defender */ GamepadCommands::exit, /* 12 - 4 on defender */ GamepadCommands::none, /* 13 - 1 on defender */ - GamepadCommands::none, /* 14 */ }, sticksBinding { - GamepadCommands::moveRobotX, /* 1 - left X */ - GamepadCommands::moveRobotY, /* 2 - left Y */ - GamepadCommands::moveCameraX, /* 3 - right X */ - GamepadCommands::moveCameraY, /* 4 - right Y */ + GamepadCommands::moveRobotX, /* 0 - left X */ + GamepadCommands::moveRobotY, /* 1 - left Y */ + GamepadCommands::moveCameraX, /* 2 - right X */ + GamepadCommands::moveCameraY, /* 3 - right Y */ + GamepadCommands::none, /* 4 */ GamepadCommands::none, /* 5 */ - GamepadCommands::none, /* 6 */ } { } @@ -37,3 +37,16 @@ GamepadCommands GamepadConfig::stick(int index) const { return ((index >= 0) && (index < maxSticks)) ? sticksBinding[index] : GamepadCommands::none; } + +int GamepadConfig::getStickId(GamepadCommands command) const +{ + for (auto i = 0; i < maxButtons; ++i) + { + if (buttonsBinding[i] == command) + { + return i; + } + } + + return badIndex; +} diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.h b/code/c++/cxx-gamepad-app/GamepadConfig.h index 760ba0b..997ae4e 100644 --- a/code/c++/cxx-gamepad-app/GamepadConfig.h +++ b/code/c++/cxx-gamepad-app/GamepadConfig.h @@ -37,6 +37,14 @@ class GamepadConfig * @return Button mapping command or @GamepadCommands::none, if not exists */ GamepadCommands stick(int index) const; + + /** + * Convert command to stick id that binds with that command + * @return Binding key index or @badIndex, if not exists + */ + int getStickId(GamepadCommands command) const; + + static const int badIndex = -1; }; #endif /* _GAMEPAD_CONFIG_H_ */ diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp index 7a92f85..b71edbe 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.cpp +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -4,7 +4,9 @@ #include "GamepadManager.h" -GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), isRunningNow(new std::mutex), runnedThread(nullptr) +const double GamepadManager::forwardMultiplier = 0.6; + +GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), runnedThread(nullptr) { Gamepad_buttonDownFunc(onButtonDown, (void *)this); Gamepad_buttonUpFunc(onButtonUp, (void *)this); @@ -16,10 +18,6 @@ GamepadManager::~GamepadManager() { stop(); join(); - if (isRunningNow) - { - delete isRunningNow; - } if (runnedThread) { delete runnedThread; @@ -29,26 +27,36 @@ GamepadManager::~GamepadManager() void GamepadManager::run() { + isRequireToRun = true; + runnedThread = runnedThread ? runnedThread : new std::thread([this]() { - while (this->isRunningNow && !this->isRunningNow->try_lock()) + while (this->isRequireToRun) { Gamepad_detectDevices(); Gamepad_processEvents(); } - - this->isRunningNow->unlock(); }); } void GamepadManager::stop() { - //TODO + isRequireToRun = false; } void GamepadManager::join() { - //TODO + if (!runnedThread) + { + return; + } + + if (runnedThread->joinable()) + { + runnedThread->join(); + } + delete runnedThread; + runnedThread = nullptr; } const GamepadConfig& GamepadManager::getConfig() const @@ -61,4 +69,22 @@ TrackPlatform_Manager* GamepadManager::getTrackPlatformManager() const return trackPlatform; } +bool GamepadManager::convertAndSendMovement(double xValue, double yValue) +{ + if (!trackPlatform) + { + return false; + } + + if (!trackPlatform->setTrackForwardSpeed(left_track, yValue * forwardMultiplier - xValue * (1 - forwardMultiplier))) + { + return false; + } + + if (!trackPlatform->setTrackForwardSpeed(right_track, yValue * forwardMultiplier + xValue * (1 - forwardMultiplier))) + { + return false; + } + + return true; } diff --git a/code/c++/cxx-gamepad-app/GamepadManager.h b/code/c++/cxx-gamepad-app/GamepadManager.h index ab40fe3..6e736d2 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.h +++ b/code/c++/cxx-gamepad-app/GamepadManager.h @@ -1,7 +1,8 @@ #ifndef _GAMEPAD_MANAGER_H_ #define _GAMEPAD_MANAGER_H_ -#include +#include +#include #include "TrackPlatform_Manager.h" #include "GamepadConfig.h" @@ -11,7 +12,7 @@ class GamepadManager /** * @brief mutex is locked when handler thread is running, else not locked */ - std::mutex * isRunningNow = nullptr; + std::atomic_bool isRequireToRun = false; /** * @brief Handler thread pointer */ @@ -19,6 +20,8 @@ class GamepadManager GamepadConfig config; + static const double forwardMultiplier; + public: GamepadManager(TrackPlatform_Manager* trackPlatform); ~GamepadManager(); @@ -44,6 +47,13 @@ class GamepadManager * @return Current trackPlatform manager */ TrackPlatform_Manager* getTrackPlatformManager() const; + /** + * @brief Convert gamepad x and y values to movement speed of tracks and send it to device + * @param xValue X axis value (must be in interval [-1; 1]) + * @param yValue Y axis value (must be in interval [-1; 1]) + * @return true, if all were successed, else false + */ + bool convertAndSendMovement(double xValue, double yValue); }; #endif /* _GAMEPAD_MANAGER_H_ */ diff --git a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp index c2c373b..ca877b4 100644 --- a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp +++ b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp @@ -33,7 +33,20 @@ void onAxisMoved(Gamepad_device* device, unsigned axisID, float value, float las GamepadManager* manager = static_cast(context); switch (manager->getConfig().stick(axisID)) { - //TODO: process sticks + case GamepadCommands::moveRobotX: + case GamepadCommands::moveRobotY: { + auto config = manager->getConfig(); + manager->convertAndSendMovement(device->axisStates[config.getStickId(GamepadCommands::moveRobotX)], device->axisStates[config.getStickId(GamepadCommands::moveRobotY)]); + break; + } + case GamepadCommands::moveCameraX: { + manager->getTrackPlatformManager()->servoSetHorizontalAngle(static_cast((value + 1) * 90)); + break; + } + case GamepadCommands::moveCameraY: { + manager->getTrackPlatformManager()->servoSetVerticalAngle(static_cast((value + 1) * 90)); + break; + } default: break; } } diff --git a/code/c++/cxx-gamepad-app/main.cpp b/code/c++/cxx-gamepad-app/main.cpp index 888e70f..f5ba53d 100644 --- a/code/c++/cxx-gamepad-app/main.cpp +++ b/code/c++/cxx-gamepad-app/main.cpp @@ -17,6 +17,7 @@ int main(int argc, char* argv[]) TrackPlatform_Manager trackPlatform(bluetooth, rtx, rtx, baudrate); GamepadManager manager(&trackPlatform); manager.run(); + manager.join(); } catch(...) { From f25a5d10859972632d7fc77c1c2a6465bd2a728c Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 15:16:18 +0300 Subject: [PATCH 056/336] =?UTF-8?q?Debug=20UART=20=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=D1=8E=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D0=B5=D0=B4=D0=B5=D0=BD=20=D0=BD=D0=B0=20HardwareSerial.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 4 ++-- code/Arduino/connectors/DebugSerial.cpp | 6 ++++++ code/Arduino/connectors/DebugSerial.h | 6 ++++++ code/Arduino/peripheral/ServoController.h | 1 - 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 302008c..53bdfb8 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -16,8 +16,8 @@ const uint32_t Constants::wifi_serial_speed = 115200; const uint32_t Constants::usb_serial_speed = 9600; /* Debug serial (Hardware Serial1 maybe will be in future) */ -const uint8_t Constants::dbg_uart_RX = 52; -const uint8_t Constants::dbg_uart_TX = 53; +const uint8_t Constants::dbg_uart_RX = 19; +const uint8_t Constants::dbg_uart_TX = 18; const uint32_t Constants::dbg_uart_speed = 9600; /* Movement controller (L298N) */ diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp index 3686a22..3be4c08 100644 --- a/code/Arduino/connectors/DebugSerial.cpp +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -5,6 +5,7 @@ #ifdef DEBUG_ON HardwareSerial* DebugSerial::serial = &Serial1; +bool DebugSerial::isInited = false; SoftwareSerial* DebugSerial::generateDbgSerial() { @@ -16,6 +17,11 @@ SoftwareSerial* DebugSerial::generateDbgSerial() DebugSerial::DebugSerial(): ConnectingDevice(serial) { + if (!isInited) + { + isInited = true; + serial->begin(Constants::dbg_uart_speed); + } } Stream* DebugSerial::getSerial() diff --git a/code/Arduino/connectors/DebugSerial.h b/code/Arduino/connectors/DebugSerial.h index 0e8b434..7056d3d 100644 --- a/code/Arduino/connectors/DebugSerial.h +++ b/code/Arduino/connectors/DebugSerial.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "ConnectingDevice.h" @@ -33,6 +34,11 @@ class DebugSerial : public ConnectingDevice static const int printfBuffSize = 120; static SoftwareSerial* generateDbgSerial(); + /** + * @brief Block for double initialization + */ + static bool isInited; + public: DebugSerial(); diff --git a/code/Arduino/peripheral/ServoController.h b/code/Arduino/peripheral/ServoController.h index 8a70bf6..51c4e8a 100644 --- a/code/Arduino/peripheral/ServoController.h +++ b/code/Arduino/peripheral/ServoController.h @@ -4,7 +4,6 @@ /** * @brief Servo controller for 2 axes: X & Y - * @attention Turn off debug console to correct working * @attention Create only one object of that class. And create it in setup() method only */ class ServoController : public MainController From fdf5fc168f196aa8a815b59f4884aa1462b00b97 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 15:40:43 +0300 Subject: [PATCH 057/336] =?UTF-8?q?GamepadConfig::getStickId()=20fix.=20?= =?UTF-8?q?=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D1=81=D0=BE=D0=BE=D0=B1?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B4=D0=B2=D0=B8=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B4=D0=BE=D1=85=D0=BE=D0=B4=D1=8F=D1=82=20=D0=B4?= =?UTF-8?q?=D0=BE=20=D1=80=D0=BE=D0=B1=D0=BE=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-gamepad-app/GamepadConfig.cpp b/code/c++/cxx-gamepad-app/GamepadConfig.cpp index ee66f96..d952bb5 100644 --- a/code/c++/cxx-gamepad-app/GamepadConfig.cpp +++ b/code/c++/cxx-gamepad-app/GamepadConfig.cpp @@ -40,9 +40,9 @@ GamepadCommands GamepadConfig::stick(int index) const int GamepadConfig::getStickId(GamepadCommands command) const { - for (auto i = 0; i < maxButtons; ++i) + for (auto i = 0; i < maxSticks; ++i) { - if (buttonsBinding[i] == command) + if (sticksBinding[i] == command) { return i; } From 188e3ee8723aabaa6c033fd61d5fef0981f4142f Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 16:16:08 +0300 Subject: [PATCH 058/336] =?UTF-8?q?TrackPlatform=5FBasicManagement::setTra?= =?UTF-8?q?ckForwardSpeed()=20fix.=20=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D1=8F=D0=B5=D0=BC=D0=B0=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D0=BD=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicManagement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 984cb69..8825a44 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -127,7 +127,7 @@ bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double return false; } - std::string toSend(1, back_speed); + std::string toSend(1, track_set_speed); toSend += std::to_string(*reinterpret_cast(&trackId)); toSend += delimiter; toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); From 4b7903d2ba67fbba36367f0aa0c0b5a40cff8fbc Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 23:24:02 +0300 Subject: [PATCH 059/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BA=20=D0=BA=D0=B0=D0=B6=D0=B4=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D0=BC?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=B5=20?= =?UTF-8?q?=D0=B2=20=D1=82=D0=B5=D0=BA=D1=81=D1=82=D0=BE=D0=B2=D0=BE=D0=BC?= =?UTF-8?q?=20=D0=B2=D0=B8=D0=B4=D0=B5,=20=D0=B5=D1=81=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=B0=20=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D0=B0=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/peripheral/MovementController.cpp | 11 +++++++++++ code/Arduino/peripheral/SensorsController.cpp | 4 ++++ code/Arduino/peripheral/ServoController.cpp | 2 ++ 3 files changed, 17 insertions(+) diff --git a/code/Arduino/peripheral/MovementController.cpp b/code/Arduino/peripheral/MovementController.cpp index 1328216..ceb1038 100644 --- a/code/Arduino/peripheral/MovementController.cpp +++ b/code/Arduino/peripheral/MovementController.cpp @@ -1,4 +1,5 @@ #include "../CommandsEnum.h" +#include "../connectors/DebugSerial.h" #include "MovementController.h" MovementController::MovementController() @@ -58,16 +59,19 @@ void MovementController::exec(ConnectingDevice *device, String command) { void MovementController::move_forward() { + DEBUG_PRINTLN("Move forward"); left_track_control(forward_direction, MAX_SPEED); right_track_control(forward_direction, MAX_SPEED); } void MovementController::move_forward(int speed) { + DEBUG_PRINTF("Move forward with speed %d\n", speed); left_track_control(forward_direction, speed); right_track_control(forward_direction, speed); } void MovementController::move_forward(int speed, int time_ms) { + DEBUG_PRINTF("Move forward with speed %d with time %d ms\n", speed, time_ms); left_track_control(forward_direction, speed); right_track_control(forward_direction, speed); delay(time_ms); @@ -75,26 +79,31 @@ void MovementController::move_forward(int speed, int time_ms) { } void MovementController::move_back() { + DEBUG_PRINTF("Move backward\n"); left_track_control(back_direction, MAX_SPEED); right_track_control(back_direction, MAX_SPEED); } void MovementController::move_back(int speed) { + DEBUG_PRINTF("Move backward with speed %d\n", speed); left_track_control(back_direction, speed); right_track_control(back_direction, speed); } void MovementController::turn_left() { + DEBUG_PRINTF("Turn left\n"); left_track_control(forward_direction, MAX_SPEED); right_track_control(back_direction, MAX_SPEED); } void MovementController::turn_right() { + DEBUG_PRINTF("Turn right\n"); left_track_control(back_direction, MAX_SPEED); right_track_control(forward_direction, MAX_SPEED); } void MovementController::stop_moving() { + DEBUG_PRINTF("Stop moving\n"); analogWrite(constants.left_engine_enable, MIN_SPEED); analogWrite(constants.right_engine_enable, MIN_SPEED); digitalWrite(constants.left_engine_straight_pin, LOW); @@ -104,6 +113,7 @@ void MovementController::stop_moving() { } void MovementController::choose_track_set_speed(int trackID, int speed) { + DEBUG_PRINTF("Track set speed. TrackID = %d, speed = %d\n", trackID, speed); switch (trackID) { case left_track: @@ -118,6 +128,7 @@ void MovementController::choose_track_set_speed(int trackID, int speed) { } void MovementController::choose_track_set_speed(int* arr) { + DEBUG_PRINTF("Track set speed. TrackID = %d, speed = %d\n", arr[0], arr[1]); switch (arr[0]) { case left_track: diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index 3aa1009..5dce183 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -27,15 +27,19 @@ void SensorsController::exec(ConnectingDevice *device, String command) { switch (command[1]) { case distance_sensor: + DEBUG_PRINTF("Get distance sensor %d value\n", parse_command(command, 2, command.length())); device->send(String(getDistance(parse_command(command, 2, command.length())))); break; case distance_sensor_all: + DEBUG_PRINTF("Get all distance sensor values\n"); device->send(intArrayToString(arr = getDistanceAll(), countDistanceSensors)); break; case line_sensor: + DEBUG_PRINTF("Get line sensor %d value\n", parse_command(command, 2, command.length())); device->send(String(getLine(parse_command(command, 2, command.length())))); break; case line_sensor_all: + DEBUG_PRINTF("Get all line sensor values\n"); device->send(intArrayToString(arr = getLineAll(), countLineSensors)); break; default: diff --git a/code/Arduino/peripheral/ServoController.cpp b/code/Arduino/peripheral/ServoController.cpp index aad96f3..9305cc7 100644 --- a/code/Arduino/peripheral/ServoController.cpp +++ b/code/Arduino/peripheral/ServoController.cpp @@ -41,6 +41,7 @@ void ServoController::exec(ConnectingDevice* device, String command) { } void ServoController::setHorizontalAngle(int angle) { + DEBUG_PRINTF("Set servo horizontal angle %d\n", angle); horizontalServo.write(angle); delay(constants.servo_delay); } @@ -59,6 +60,7 @@ void ServoController::setHorizontalAndVerticalAngle(int angleX, int angleY) { } int* ServoController::getCoordinates() { + DEBUG_PRINTF("Get servo coordinates\n"); int* arr = new int[2]; arr[0] = getHorizontalAngel(); arr[1] = getVerticalAngel(); From 22bf5f8b52cd195cf9ab704dc593c2378476d245 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Fri, 18 Aug 2017 23:46:42 +0300 Subject: [PATCH 060/336] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7=D0=B1=D0=BE=D1=80=20?= =?UTF-8?q?=D0=BC=D0=B0=D1=81=D1=81=D0=B8=D0=B2=D0=BE=D0=B2=20=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D0=B5=D0=BB=20(=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D0=BE=D0=BD=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/peripheral/MainController.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/code/Arduino/peripheral/MainController.cpp b/code/Arduino/peripheral/MainController.cpp index 6df8a35..af4d092 100644 --- a/code/Arduino/peripheral/MainController.cpp +++ b/code/Arduino/peripheral/MainController.cpp @@ -7,9 +7,21 @@ MainController::MainController() { int* MainController::parse_command(String command, int begin, char delimetr, int paramsLength) { int* arr = new int[paramsLength]; + // clean all allocated memory (can use memset from cstdlib) + for (int i = 0; i < paramsLength; ++i) + { + arr[i] = 0; + } + command = command.substring(begin); + begin = 0; int delimetrPos = command.indexOf(delimetr); - for (int i = 0; (i < paramsLength) && (delimetrPos >= 0); i++) { + for (int i = 0; (i < paramsLength); i++) { + if ((delimetrPos < 0)) + { + arr[i] = command.substring(begin).toInt(); + break; + } arr[i] = command.substring(begin, delimetrPos).toInt(); command = command.substring(delimetrPos + 1); begin = 0; From bb79f722980901cce0ac1309ec4f8e2b55610853 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 19 Aug 2017 21:37:42 +0300 Subject: [PATCH 061/336] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=20MovementContoroller=20=D1=81=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=D0=BC=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=20=D0=B8=20=D1=81=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Arduino/peripheral/MovementController.cpp | 53 ++++++++++--------- code/Arduino/peripheral/MovementController.h | 12 +++++ 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/code/Arduino/peripheral/MovementController.cpp b/code/Arduino/peripheral/MovementController.cpp index ceb1038..47874a8 100644 --- a/code/Arduino/peripheral/MovementController.cpp +++ b/code/Arduino/peripheral/MovementController.cpp @@ -2,6 +2,33 @@ #include "../connectors/DebugSerial.h" #include "MovementController.h" +void MovementController::track_control(bool direction, int speed, uint8_t enablePin, uint8_t straightPin, uint8_t reversePin) +{ + if (!isPinNumGood(enablePin) || !isPinNumGood(straightPin) || !isPinNumGood(reversePin)) { + return; + } + + speed = (speed > MAX_SPEED) ? MAX_SPEED : ((speed < -MAX_SPEED) ? -MAX_SPEED : speed); + if (speed < 0) + { + speed = -speed; + direction = !direction; + } + analogWrite(enablePin, speed); + if (direction == forward_direction) { + digitalWrite(straightPin, LOW); + digitalWrite(reversePin, HIGH); + } else { + digitalWrite(straightPin, HIGH); + digitalWrite(reversePin, LOW); + } +} + +bool MovementController::isPinNumGood(uint8_t pin) +{ + return (pin <= A15); +} + MovementController::MovementController() { MIN_SPEED = constants.min_speed; @@ -143,33 +170,11 @@ void MovementController::choose_track_set_speed(int* arr) { } void MovementController::left_track_control(bool direction, int speed) { - analogWrite(constants.left_engine_enable, speed); - switch (direction) { - case forward_direction: - digitalWrite(constants.left_engine_straight_pin, LOW); - digitalWrite(constants.left_engine_reverse_pin, HIGH); - break; - - case back_direction: - digitalWrite(constants.left_engine_straight_pin, HIGH); - digitalWrite(constants.left_engine_reverse_pin, LOW); - break; - } + track_control(direction, speed, constants.left_engine_enable, constants.left_engine_straight_pin, constants.left_engine_reverse_pin); } void MovementController::right_track_control(bool direction, int speed) { - analogWrite(constants.right_engine_enable, speed); - switch (direction) { - case forward_direction: - digitalWrite(constants.right_engine_straight_pin, LOW); - digitalWrite(constants.right_engine_reverse_pin, HIGH); - break; - - case back_direction: - digitalWrite(constants.right_engine_straight_pin, HIGH); - digitalWrite(constants.right_engine_reverse_pin, LOW); - break; - } + track_control(direction, speed, constants.right_engine_enable, constants.right_engine_straight_pin, constants.right_engine_reverse_pin); } MovementController::~MovementController() diff --git a/code/Arduino/peripheral/MovementController.h b/code/Arduino/peripheral/MovementController.h index d6768b9..9783152 100644 --- a/code/Arduino/peripheral/MovementController.h +++ b/code/Arduino/peripheral/MovementController.h @@ -9,6 +9,18 @@ class MovementController : public MainController int MIN_SPEED; int MAX_SPEED; + /** + * @brief All track control + * + * @param direction Main direction (what direction will be positive in @speed param) + * @param speed Speed of control (must be in [-255, 255] ([-@MAX_SPEED, @MAX_SPEED]) range) + * @param enablePin Pin to enable track + * @param straightPin Pin to forward direction (LOW = enable forward direction) + * @param reversePin Pin to backward direction (LOW = enable backward direction) + */ + void track_control(bool direction, int speed, uint8_t enablePin, uint8_t straightPin, uint8_t reversePin); + + static bool isPinNumGood(uint8_t pin); public: MovementController(); void exec(ConnectingDevice *device, String); From 3bcdfd3208322bd3593d2096e2f7545401de9407 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 19 Aug 2017 22:30:39 +0300 Subject: [PATCH 062/336] Warning fixes --- code/Arduino/connectors/DebugSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Arduino/connectors/DebugSerial.cpp b/code/Arduino/connectors/DebugSerial.cpp index 3be4c08..2477e73 100644 --- a/code/Arduino/connectors/DebugSerial.cpp +++ b/code/Arduino/connectors/DebugSerial.cpp @@ -46,7 +46,7 @@ void DebugSerial::println(String data) void DebugSerial::printHex(String data) { - for (int i = 0; i < data.length(); ++i) + for (unsigned int i = 0; i < data.length(); ++i) { printf("%02X ", data[i]); } From 3f3baac18ae40bfaa42b29b8e96c986ae5ee44c1 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 19 Aug 2017 22:32:57 +0300 Subject: [PATCH 063/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=84=D0=B0=D0=B9?= =?UTF-8?q?=D0=BB=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20(=D0=BF=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8E=20=D0=B2=D1=8B=D0=BA=D0=BB=D1=8E=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/Logger.cpp | 27 ++++++++++++++ code/c++/cxx-api/Logger.h | 36 +++++++++++++++++++ .../cxx-api/TrackPlatform_BasicConnector.cpp | 2 ++ code/c++/cxx-api/cxx-api.vcxproj | 2 ++ code/c++/cxx-api/cxx-api.vcxproj.filters | 6 ++++ code/c++/cxx-gamepad-app/main.cpp | 5 +++ 6 files changed, 78 insertions(+) create mode 100644 code/c++/cxx-api/Logger.cpp create mode 100644 code/c++/cxx-api/Logger.h diff --git a/code/c++/cxx-api/Logger.cpp b/code/c++/cxx-api/Logger.cpp new file mode 100644 index 0000000..a23529a --- /dev/null +++ b/code/c++/cxx-api/Logger.cpp @@ -0,0 +1,27 @@ +#include "Logger.h" + +#ifndef LOGGER_ON + +void Logger::log(std::string s) +{ +} + +#else + +Logger* Logger::logger = new Logger(); + +Logger::Logger() : file(way, std::ios::out | std::ios::app) +{ +} + +void Logger::logOneString(std::string s) +{ + file << s << std::endl; +} + +void Logger::log(std::string s) +{ + logger->logOneString(s); +} + +#endif diff --git a/code/c++/cxx-api/Logger.h b/code/c++/cxx-api/Logger.h new file mode 100644 index 0000000..e663c00 --- /dev/null +++ b/code/c++/cxx-api/Logger.h @@ -0,0 +1,36 @@ +#ifndef _LOGGER_H_ +#define _LOGGER_H_ + +/** + * @brief If defined, log is on, else off + */ +// #define LOGGER_ON + +#ifndef LOGGER_ON +#include +class Logger +{ +public: + static void log(std::string s); +}; + +#else +#include +#include + +class Logger +{ + static Logger* logger; + + const std::string way = "logger.log"; + std::ofstream file; + + Logger(); + void logOneString(std::string s); + +public: + static void log(std::string s); +}; +#endif + +#endif /* _LOGGER_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index 1e2eabe..c379c3e 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -1,4 +1,5 @@ #include "TrackPlatform_BasicConnector.h" +#include "Logger.h" TrackPlatform_BasicConnector::TrackPlatform_BasicConnector() { @@ -16,4 +17,5 @@ std::string TrackPlatform_BasicConnector::readOneAnswer() void TrackPlatform_BasicConnector::sendOneCommand(const std::string& s) { write(s + stopSymbol); + Logger::log("Send: " + s + stopSymbol); } diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 16370f4..28b4db6 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -147,6 +147,7 @@ + @@ -166,6 +167,7 @@ + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 333d6ab..b20c103 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -96,6 +96,9 @@ Communication\header + + Header Files + @@ -125,5 +128,8 @@ Communication\source + + Source Files + \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/main.cpp b/code/c++/cxx-gamepad-app/main.cpp index f5ba53d..3a31f82 100644 --- a/code/c++/cxx-gamepad-app/main.cpp +++ b/code/c++/cxx-gamepad-app/main.cpp @@ -4,6 +4,7 @@ #include "GamepadManager.h" #include "ConnectionModes.h" #include "TrackPlatform_Manager.h" +#include "Logger.h" int main(int argc, char* argv[]) { @@ -12,6 +13,8 @@ int main(int argc, char* argv[]) std::cout << "rx = tx = " << rtx << "; baudrate = " << baudrate << std::endl; + Logger::log("Add is running"); + try { TrackPlatform_Manager trackPlatform(bluetooth, rtx, rtx, baudrate); @@ -22,9 +25,11 @@ int main(int argc, char* argv[]) catch(...) { std::cout << "Exception was catched" << std::endl; + Logger::log("Exception was catched"); return 1; } + Logger::log("App is closed"); return 0; } From 5c5459d78037bbaf350d072690cea4ce28d731cc Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 19 Aug 2017 22:35:27 +0300 Subject: [PATCH 064/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B8=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=B0=D0=B6?= =?UTF-8?q?=D0=B4=D0=BE=D0=B9=20=D0=B3=D1=83=D1=81=D0=B5=D0=BD=D0=B8=D1=86?= =?UTF-8?q?=D1=8B=20=D0=B2=20=D0=BF=D1=80=D0=BE=D0=BC=D0=B5=D0=B6=D1=83?= =?UTF-8?q?=D1=82=D0=BA=D0=B5=20[-1;=201]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicManagement.cpp | 2 +- code/c++/cxx-api/TrackPlatform_BasicManagement.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 8825a44..97d5cfa 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -122,7 +122,7 @@ void TrackPlatform_BasicManagement::moveStopAll() const bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double speed) const { - if (speed < 0 || speed > 1) + if (speed < -1 || speed > 1) { return false; } diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index b5258bb..abac728 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -42,7 +42,7 @@ class TrackPlatform_BasicManagement void moveStopAll() const; - //speed must be in [0,1] range + //speed must be in [-1, 1] range bool setTrackForwardSpeed(TrackID trackId, double speed) const; /* sensors controller */ From 20ba70649de126ebe9bdd54e74b66cd17a99b825 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 20 Aug 2017 12:55:14 +0300 Subject: [PATCH 065/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20flush()=20=D0=BF=D1=80=D0=B8=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BF=D0=BE=D1=80=D1=82.=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BD=D0=B0=20=D0=B2?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=D0=BD=D1=8B=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=BC=D0=B5=D1=82=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=20GamepadManager::convertAndSendMovement()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/SerialConnector.cpp | 1 + code/c++/cxx-gamepad-app/GamepadManager.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index a701c52..107cb18 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -3,6 +3,7 @@ void SerialConnector::write(const std::string& s) { writePort->write(s); + writePort->flush(); } SerialConnector::SerialConnector(const std::string& rx, const std::string& tx, uint32_t baudRate) : diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp index b71edbe..df6ca7b 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.cpp +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -71,7 +71,7 @@ TrackPlatform_Manager* GamepadManager::getTrackPlatformManager() const bool GamepadManager::convertAndSendMovement(double xValue, double yValue) { - if (!trackPlatform) + if (!trackPlatform || (xValue > 1) || (xValue < -1) || (yValue > 1) || (yValue < -1)) { return false; } From 6915c985c5b3179f20add59f97803b086d005578 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 20 Aug 2017 13:34:39 +0300 Subject: [PATCH 066/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=B1?= =?UTF-8?q?=D0=B5=D0=B7=D0=BE=D0=BF=D0=B0=D1=81=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B4=D0=BB=D1=8F=20TrackPlatform=5FBasicManagement?= =?UTF-8?q?=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20(=D1=82.=D0=B5.=20?= =?UTF-8?q?=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B2=D1=81=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D1=87=D0=BD=D1=8B=D0=B5=20=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=20=D1=81=D1=87=D0=B8=D1=82=D0=B0=D1=82=D1=8C=20=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D0=BC=D0=B0=D1=80=D0=BD=D1=8B=D0=BC=D0=B8).=20=D0=A3?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=BD=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=B4=20=D0=B8=D0=B7=20=D0=BF=D1=80=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D1=80=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cxx-api/TrackPlatform_BasicManagement.cpp | 65 ++++++++++++------- .../cxx-api/TrackPlatform_BasicManagement.h | 43 ++++++------ code/c++/cxx-app/main.cpp | 7 -- 3 files changed, 65 insertions(+), 50 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 8825a44..a935f57 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -1,18 +1,24 @@ #include "TrackPlatform_BasicManagement.h" -void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) const +void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) { + readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(movementControllerID) + additionalInfo); + readWriteAtomicMutex.unlock(); } -void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInfo) const +void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInfo) { + readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(sensorsControllerID) + additionalInfo); + readWriteAtomicMutex.unlock(); } -void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) const +void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) { + readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(servoControllerID) + additionalInfo); + readWriteAtomicMutex.unlock(); } std::vector TrackPlatform_BasicManagement::parseStringToArray(std::string s) @@ -55,13 +61,13 @@ TrackPlatform_BasicManagement::~TrackPlatform_BasicManagement() { } -void TrackPlatform_BasicManagement::moveForward() const +void TrackPlatform_BasicManagement::moveForward() { std::string toSend(1, forward); sendMove(toSend); } -bool TrackPlatform_BasicManagement::moveForward(double speed) const +bool TrackPlatform_BasicManagement::moveForward(double speed) { if (speed < 0 || speed > 1) { @@ -75,20 +81,20 @@ bool TrackPlatform_BasicManagement::moveForward(double speed) const return true; } -void TrackPlatform_BasicManagement::moveForward(uint32_t timeInMSec) const +void TrackPlatform_BasicManagement::moveForward(uint32_t timeInMSec) { std::string toSend(1, forward_time); toSend += std::to_string(timeInMSec); sendMove(toSend); } -void TrackPlatform_BasicManagement::moveBackward() const +void TrackPlatform_BasicManagement::moveBackward() { std::string toSend(1, back); sendMove(toSend); } -bool TrackPlatform_BasicManagement::moveBackward(double speed) const +bool TrackPlatform_BasicManagement::moveBackward(double speed) { if (speed < 0 || speed > 1) { @@ -102,25 +108,25 @@ bool TrackPlatform_BasicManagement::moveBackward(double speed) const return true; } -void TrackPlatform_BasicManagement::rotateClockwise() const +void TrackPlatform_BasicManagement::rotateClockwise() { std::string toSend(1, right); sendMove(toSend); } -void TrackPlatform_BasicManagement::rotateAntiClockwise() const +void TrackPlatform_BasicManagement::rotateAntiClockwise() { std::string toSend(1, left); sendMove(toSend); } -void TrackPlatform_BasicManagement::moveStopAll() const +void TrackPlatform_BasicManagement::moveStopAll() { std::string toSend(1, stop); sendMove(toSend); } -bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double speed) const +bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double speed) { if (speed < 0 || speed > 1) { @@ -136,53 +142,63 @@ bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double return true; } -uint32_t TrackPlatform_BasicManagement::sensorDistanceGetValue(uint8_t num) const +uint32_t TrackPlatform_BasicManagement::sensorDistanceGetValue(uint8_t num) { std::string toSend(1, distance_sensor); toSend += std::to_string(num); + readWriteAtomicMutex.lock(); sendSensors(toSend); auto answer = connector->readOneAnswer(); + readWriteAtomicMutex.unlock(); return std::stoi(answer); } -std::vector TrackPlatform_BasicManagement::sensorDistanceGetAllValues() const +std::vector TrackPlatform_BasicManagement::sensorDistanceGetAllValues() { std::string toSend(1, distance_sensor_all); + readWriteAtomicMutex.lock(); sendSensors(toSend); - return parseStringToArray(connector->readOneAnswer()); + auto answer = connector->readOneAnswer(); + readWriteAtomicMutex.unlock(); + return parseStringToArray(answer); } -uint32_t TrackPlatform_BasicManagement::sensorLineGetValue(uint8_t num) const +uint32_t TrackPlatform_BasicManagement::sensorLineGetValue(uint8_t num) { std::string toSend(1, line_sensor); toSend += std::to_string(num); + readWriteAtomicMutex.lock(); sendSensors(toSend); auto answer = connector->readOneAnswer(); + readWriteAtomicMutex.unlock(); return std::stoi(answer); } -std::vector TrackPlatform_BasicManagement::sensorLineGetAllValues() const +std::vector TrackPlatform_BasicManagement::sensorLineGetAllValues() { std::string toSend(1, line_sensor_all); + readWriteAtomicMutex.lock(); sendSensors(toSend); - return parseStringToArray(connector->readOneAnswer()); + auto answer = connector->readOneAnswer(); + readWriteAtomicMutex.unlock(); + return parseStringToArray(answer); } -void TrackPlatform_BasicManagement::servoSetHorizontalAngle(uint16_t angle) const +void TrackPlatform_BasicManagement::servoSetHorizontalAngle(uint16_t angle) { std::string toSend(1, set_horizontal_angle); toSend += std::to_string(angle); sendServo(toSend); } -void TrackPlatform_BasicManagement::servoSetVerticalAngle(uint16_t angle) const +void TrackPlatform_BasicManagement::servoSetVerticalAngle(uint16_t angle) { std::string toSend(1, set_vertical_angle); toSend += std::to_string(angle); sendServo(toSend); } -void TrackPlatform_BasicManagement::servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle) const +void TrackPlatform_BasicManagement::servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle) { std::string toSend(1, set_horiz_vertical_angles); toSend += std::to_string(horizontalAngle); @@ -191,9 +207,12 @@ void TrackPlatform_BasicManagement::servoSetHorizontalVerticalAngle(uint16_t hor sendServo(toSend); } -std::vector TrackPlatform_BasicManagement::servoGetAngles() const +std::vector TrackPlatform_BasicManagement::servoGetAngles() { std::string toSend(1, get_coodrinates); + readWriteAtomicMutex.lock(); sendServo(toSend); - return parseStringToArray(connector->readOneAnswer()); + auto answer = connector->readOneAnswer(); + readWriteAtomicMutex.unlock(); + return parseStringToArray(answer); } diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index b5258bb..aa4d7d0 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -2,6 +2,7 @@ #define _TRACKPLATFORM_BASICMANAGEMENT_H_ #include +#include #include "TrackPlatform_BasicConnector.h" #include "CommandsEnum.h" @@ -15,47 +16,49 @@ class TrackPlatform_BasicManagement static const char delimiter = ';'; protected: - void sendMove(const std::string& additionalInfo) const; - void sendSensors(const std::string& additionalInfo) const; - void sendServo(const std::string& additionalInfo) const; + void sendMove(const std::string& additionalInfo); + void sendSensors(const std::string& additionalInfo); + void sendServo(const std::string& additionalInfo); static std::vector parseStringToArray(std::string s); TrackPlatform_BasicConnector* getConnector() const; + std::recursive_mutex readWriteAtomicMutex; + public: TrackPlatform_BasicManagement(TrackPlatform_BasicConnector* connector); virtual ~TrackPlatform_BasicManagement(); /* movement controller */ - void moveForward() const; + void moveForward(); //speed must be in [0,1] range - bool moveForward(double speed) const; - void moveForward(uint32_t timeInMSec) const; + bool moveForward(double speed); + void moveForward(uint32_t timeInMSec); - void moveBackward() const; + void moveBackward(); //speed must be in [0,1] range - bool moveBackward(double speed) const; + bool moveBackward(double speed); - void rotateClockwise() const; - void rotateAntiClockwise() const; + void rotateClockwise(); + void rotateAntiClockwise(); - void moveStopAll() const; + void moveStopAll(); //speed must be in [0,1] range - bool setTrackForwardSpeed(TrackID trackId, double speed) const; + bool setTrackForwardSpeed(TrackID trackId, double speed); /* sensors controller */ - uint32_t sensorDistanceGetValue(uint8_t num) const; - std::vector sensorDistanceGetAllValues() const; - uint32_t sensorLineGetValue(uint8_t num) const; - std::vector sensorLineGetAllValues() const; + uint32_t sensorDistanceGetValue(uint8_t num); + std::vector sensorDistanceGetAllValues(); + uint32_t sensorLineGetValue(uint8_t num); + std::vector sensorLineGetAllValues(); /* servo controller */ - void servoSetHorizontalAngle(uint16_t angle) const; - void servoSetVerticalAngle(uint16_t angle) const; - void servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle) const; - std::vector servoGetAngles() const; + void servoSetHorizontalAngle(uint16_t angle); + void servoSetVerticalAngle(uint16_t angle); + void servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle); + std::vector servoGetAngles(); }; #endif /* _TRACKPLATFORM_BASICMANAGEMENT_H_ */ diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 7589001..2cca064 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -9,11 +9,6 @@ #endif #include "TrackPlatform_Manager.h" -#if defined(_WIN32) -#include "platform_dependent/windows/TCPIP_Connector.h" -#else -#include "platform_dependent/Linux/TCPIP_Connector.h" -#endif int main(int argc, char* argv[]) { @@ -29,8 +24,6 @@ int main(int argc, char* argv[]) */ std::cout << "rx = " << rx << " tx = " << tx << " baudrate = " << baudrate << std::endl; - TCPIP_Connector tcpip("127.0.0.1", 3333); - try { TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, baudrate); From d7fa49cb13351a0491dbc19246ba41d23aada10d Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 20 Aug 2017 15:08:16 +0300 Subject: [PATCH 067/336] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=20TrackPlatform=5FManager.=20=D0=A2=D0=B5=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D1=8C=20=D0=BE=D0=BD=20=D0=BC=D0=BE=D0=B6=D0=B5?= =?UTF-8?q?=D1=82=20=D0=BF=D1=80=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=BE=20=D0=BB=D1=8E=D0=B1=D0=BE=D0=BC=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B8.=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20WiFi=20=D0=B2=20Tr?= =?UTF-8?q?ackPlatform=5FManager=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/CommunicationInfoStruct.h | 25 ++ code/c++/cxx-api/TrackPlatform_Manager.cpp | 14 +- code/c++/cxx-api/TrackPlatform_Manager.h | 5 +- code/c++/cxx-api/cxx-api.vcxproj | 1 + code/c++/cxx-api/cxx-api.vcxproj.filters | 256 +++++++++++---------- code/c++/cxx-app/main.cpp | 6 +- 6 files changed, 173 insertions(+), 134 deletions(-) create mode 100644 code/c++/cxx-api/CommunicationInfoStruct.h diff --git a/code/c++/cxx-api/CommunicationInfoStruct.h b/code/c++/cxx-api/CommunicationInfoStruct.h new file mode 100644 index 0000000..0380f67 --- /dev/null +++ b/code/c++/cxx-api/CommunicationInfoStruct.h @@ -0,0 +1,25 @@ +#ifndef _COMMUNICATION_INFO_STRUCT_H_ +#define _COMMUNICATION_INFO_STRUCT_H_ +#include +#include + +/** + * @brief Information to communicator. + * @attention You must fill info about required communication before send it to class constructor + */ +struct CommunicationInfoStruct +{ + struct + { + std::string rxPort; + std::string txPort; + uint32_t baudrate; + } SerialInfo; + struct + { + std::string ip; + uint16_t port; + } TCPIPInfo; +}; + +#endif /* _COMMUNICATION_INFO_STRUCT_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index e2f9706..2ad92f4 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -1,7 +1,8 @@ #include "TrackPlatform_Manager.h" #include "SerialConnector.h" +#include "TCPIP_Connector.h" -TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate) +TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(ConnectionModes mode, const CommunicationInfoStruct& info) { TrackPlatform_BasicConnector* res; @@ -9,10 +10,11 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne switch (mode) { case USB: - res = new SerialConnector(rx, tx, baudRate); - break; case bluetooth: - res = new SerialConnector(rx, tx, baudRate); + res = new SerialConnector(info.SerialInfo.rxPort, info.SerialInfo.txPort, info.SerialInfo.baudrate); + break; + case WiFi: + res = new TCPIP_Connector(info.TCPIPInfo.ip, info.TCPIPInfo.port); break; default: res = nullptr; @@ -22,8 +24,8 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne return res; } -TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate) : - TrackPlatform_BasicManagement(createConnectorByMode(mode, rx, tx, baudRate)) +TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info) : + TrackPlatform_BasicManagement(createConnectorByMode(mode, info)) { } diff --git a/code/c++/cxx-api/TrackPlatform_Manager.h b/code/c++/cxx-api/TrackPlatform_Manager.h index 2f4b9bd..cd478e4 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.h +++ b/code/c++/cxx-api/TrackPlatform_Manager.h @@ -3,13 +3,14 @@ #include "TrackPlatform_BasicManagement.h" #include "ConnectionModes.h" +#include "CommunicationInfoStruct.h" class TrackPlatform_Manager : public TrackPlatform_BasicManagement { - static TrackPlatform_BasicConnector* createConnectorByMode(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate); + static TrackPlatform_BasicConnector* createConnectorByMode(ConnectionModes mode, const CommunicationInfoStruct& info); public: - TrackPlatform_Manager(ConnectionModes mode, const std::string& rx, const std::string& tx, uint32_t baudRate); + TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info); ~TrackPlatform_Manager(); }; diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 16370f4..241070a 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -147,6 +147,7 @@ + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 333d6ab..53e057c 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -1,129 +1,135 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {de9cad78-f264-4652-87a0-7f8536f7ef0c} - - - {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} - - - {a897fa9d-d634-41b6-a441-71b4a660fa92} - - - {09716c3b-089b-4880-b137-c4da5ccc81f8} - - - {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} - - - {8cb6d371-6c98-4f8c-ace2-6e3059467355} - - - {c8707437-f967-4f30-b1b5-cde6082dca67} - - - {20cccc26-6e34-4b3e-8ed5-4d44cbf4c28e} - - - {42cc74a7-2d02-4a96-828e-2b504625d84d} - - - - - Header Files - - - Header Files - - - serial_support\header - - - serial_support\header - - - serial_support\header - - - Header Files - - - Communication\header - - - Communication\header - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {de9cad78-f264-4652-87a0-7f8536f7ef0c} + + + {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} + + + {a897fa9d-d634-41b6-a441-71b4a660fa92} + + + {09716c3b-089b-4880-b137-c4da5ccc81f8} + + + {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} + + + {8cb6d371-6c98-4f8c-ace2-6e3059467355} + + + {c8707437-f967-4f30-b1b5-cde6082dca67} + + + {20cccc26-6e34-4b3e-8ed5-4d44cbf4c28e} + + + {42cc74a7-2d02-4a96-828e-2b504625d84d} + + + + + Header Files + + + Header Files + + + serial_support\header + + + serial_support\header + + + serial_support\header + + + Header Files + + + Communication\header + + + Communication\header + Communication\header - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions - - - exceptions\header - - - Communication\header - - - - - Source Files - - - serial_support\source - - - serial_support\source - - - serial_support\source - - - Source Files - - - Communication\source - - - Communication\source - - - exceptions\source - - - Communication\source - - + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions + + + exceptions\header + + + Communication\header + + + Communication + + + Communication\header + + + + + Source Files + + + serial_support\source + + + serial_support\source + + + serial_support\source + + + Source Files + + + Communication\source + + + Communication\source + + + exceptions\source + + + Communication\source + + \ No newline at end of file diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 2cca064..60a0869 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -26,7 +26,11 @@ int main(int argc, char* argv[]) try { - TrackPlatform_Manager trackPlatform(bluetooth, rx, tx, baudrate); + CommunicationInfoStruct info; + info.SerialInfo.rxPort = rx; + info.SerialInfo.txPort = tx; + info.SerialInfo.baudrate = baudrate; + TrackPlatform_Manager trackPlatform(bluetooth, info); bool isExit = false; while (!isExit) { From 1734a684834b0e9c34eacf4007d20b3ea5904b03 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 20 Aug 2017 22:28:28 +0300 Subject: [PATCH 068/336] =?UTF-8?q?=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BD=D0=B0=D1=8F=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BE=D1=82=D1=80=D0=B8=D1=86=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9=20=D0=BD=D0=B0=20=D1=80=D0=BE=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=B0=20=D0=BF=D0=BE=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=D0=B5=20"=D0=A3=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=81=D0=BA=D0=BE=D1=80=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=BD=D0=BA=D1=80?= =?UTF-8?q?=D0=B5=D1=82=D0=BD=D0=BE=D0=B9=20=D0=B3=D1=83=D1=81=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=86=D1=8B"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicManagement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 97d5cfa..9a77197 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -130,7 +130,7 @@ bool TrackPlatform_BasicManagement::setTrackForwardSpeed(TrackID trackId, double std::string toSend(1, track_set_speed); toSend += std::to_string(*reinterpret_cast(&trackId)); toSend += delimiter; - toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); + toSend += std::to_string(static_cast(speed * (maxSpeed - minSpeed) + minSpeed)); sendMove(toSend); return true; From 5cecf91e931697fa376cd5036f419c117f5e8f78 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 20 Aug 2017 23:31:22 +0300 Subject: [PATCH 069/336] Gamepad example compilation fix. --- code/c++/cxx-gamepad-app/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/c++/cxx-gamepad-app/main.cpp b/code/c++/cxx-gamepad-app/main.cpp index 3a31f82..0b5da24 100644 --- a/code/c++/cxx-gamepad-app/main.cpp +++ b/code/c++/cxx-gamepad-app/main.cpp @@ -17,7 +17,11 @@ int main(int argc, char* argv[]) try { - TrackPlatform_Manager trackPlatform(bluetooth, rtx, rtx, baudrate); + CommunicationInfoStruct info; + info.SerialInfo.rxPort = rtx; + info.SerialInfo.txPort = rtx; + info.SerialInfo.baudrate = baudrate; + TrackPlatform_Manager trackPlatform(bluetooth, info); GamepadManager manager(&trackPlatform); manager.run(); manager.join(); From 4e83a85ec93d72389455e967098cfb1004e0674d Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 20 Aug 2017 23:36:05 +0300 Subject: [PATCH 070/336] =?UTF-8?q?=D0=92=D0=BE=D1=81=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D0=BE=D0=B5=20=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20cxx-api=20?= =?UTF-8?q?=D0=B2=20Visual=20Studio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/cxx-api.vcxproj.filters | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 32b924d..4892540 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -96,6 +96,12 @@ Communication\header + + Communication + + + Header Files + @@ -129,13 +135,4 @@ Source Files - - - Communication - - - Communication\header - - - Header Files - \ No newline at end of file + \ No newline at end of file From 664d926a93616f5dc1ba4a529bac84f34423ff48 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 00:07:50 +0300 Subject: [PATCH 071/336] linux cxx-app compilation fix --- code/c++/cxx-api/makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/code/c++/cxx-api/makefile b/code/c++/cxx-api/makefile index cfbf30f..da91372 100644 --- a/code/c++/cxx-api/makefile +++ b/code/c++/cxx-api/makefile @@ -82,6 +82,7 @@ SOURCES += $(EXCEPTION_SOURCE_PATH)/TrackPlatformException.cpp # Other code (non grouped) SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_BasicManagement.cpp SOURCES += $(OTHER_SOURCE_PATH)/TrackPlatform_Manager.cpp +SOURCES += $(OTHER_SOURCE_PATH)/Logger.cpp #Include file path INCLUDES = From 977942d14950ce113b720adae6af29e358ce3af2 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 11:08:18 +0300 Subject: [PATCH 072/336] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BF=D0=BE=D0=B4=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8C=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=D0=B6=D0=BA=D0=B8=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0.=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BC=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0=D0=B4=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=20=D0=9E=D0=A1=20Linux.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/makefile | 3 ++ code/c++/cxx-app/makefile | 3 ++ code/c++/cxx-gamepad-app/gamepad_support | 2 +- code/c++/cxx-gamepad-app/makefile | 45 ++++++++++++++++++++---- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/code/c++/cxx-api/makefile b/code/c++/cxx-api/makefile index da91372..3d6bc88 100644 --- a/code/c++/cxx-api/makefile +++ b/code/c++/cxx-api/makefile @@ -24,6 +24,9 @@ USER_FLAGS ?= ############################################################################################################## # OS redefinition OS = $(shell uname -s) +ifeq ($(OS), Linux) +OS = linux +endif #Build patch BUILD_PATH = Output/$(OS) diff --git a/code/c++/cxx-app/makefile b/code/c++/cxx-app/makefile index f400c40..456aefe 100644 --- a/code/c++/cxx-app/makefile +++ b/code/c++/cxx-app/makefile @@ -24,6 +24,9 @@ USER_FLAGS ?= ############################################################################################################## # OS redefinition OS = $(shell uname -s) +ifeq ($(OS), Linux) +OS = linux +endif #Build patch BUILD_PATH = Output/$(OS) diff --git a/code/c++/cxx-gamepad-app/gamepad_support b/code/c++/cxx-gamepad-app/gamepad_support index 7cd9720..a5fac63 160000 --- a/code/c++/cxx-gamepad-app/gamepad_support +++ b/code/c++/cxx-gamepad-app/gamepad_support @@ -1 +1 @@ -Subproject commit 7cd97205f7acea05a208fcf833991e4e0b9f1cc6 +Subproject commit a5fac6306214cd1b0d56680b2c2d947ff215c61d diff --git a/code/c++/cxx-gamepad-app/makefile b/code/c++/cxx-gamepad-app/makefile index 94336bc..da0a402 100644 --- a/code/c++/cxx-gamepad-app/makefile +++ b/code/c++/cxx-gamepad-app/makefile @@ -22,8 +22,19 @@ WARNINGS_WITHOUT = #User Compiller flags USER_FLAGS ?= ############################################################################################################## -# OS redefinition +# OS and platform redefinition OS = $(shell uname -s) +OS_PLATFORM = $(shell uname -m) + +ifeq ($(OS), Linux) +OS = linux +endif +ifeq ($(OS_PLATFORM), x86_64) +OS_PLATFORM = 64 +endif +ifeq ($(OS_PLATFORM), i386) +OS_PLATFORM = 32 +endif #Build patch BUILD_PATH = Output/$(OS) @@ -63,18 +74,29 @@ endif API_FULL_PATH = $(API_BUILD_PATH)/$(API_NAME) -#Linker scrpit file -ARFLAGS = +# gamepad library path +GAMEPAD_LIB_PATH = gamepad_support +GAMEPAD_LIB_INCLUDE_PATH = $(GAMEPAD_LIB_PATH)/build/include +GAMEPAD_LIB_BUILD_PATH = $(GAMEPAD_LIB_PATH)/build/library/release-$(OS)$(OS_PLATFORM) +GAMEPAD_LIB_NAME = libstem_gamepad.a +GAMEPAD_LIB_FULL_PATH = $(GAMEPAD_LIB_BUILD_PATH)/$(GAMEPAD_LIB_NAME) + +# Linker scrpit file +LFLAGS = -lpthread #Source file path SOURCES = # Other code (non grouped) +SOURCES += $(OTHER_SOURCE_PATH)/gamepad_callbacks.cpp +SOURCES += $(OTHER_SOURCE_PATH)/GamepadConfig.cpp +SOURCES += $(OTHER_SOURCE_PATH)/GamepadManager.cpp SOURCES += $(OTHER_SOURCE_PATH)/main.cpp #Include file path INCLUDES = INCLUDES += -I$(API_INCLUDE_PATH) +INCLUDES += -I$(GAMEPAD_LIB_INCLUDE_PATH) # INCLUDES += -I$(OTHER_INCLUDE_PATH) ############################################################################################################## @@ -85,11 +107,11 @@ BIN = $(BUILD_PATH)/$(PROJECT_NAME) OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) -STATIC_LIB: $(OBJECTS) api - @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) +STATIC_LIB: $(OBJECTS) api gamepad + @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) $(GAMEPAD_LIB_FULL_PATH) $(LFLAGS) @echo -e "$(BUILD_PRINT)" -DYNAMIC_LIB: $(OBJECTS) api +DYNAMIC_LIB: $(OBJECTS) api gamepad $(error Dynamic library is not supported yet) # @$(CXX) -shared -o $(BIN) $(OBJECTS) @echo -e "$(BUILD_PRINT)" @@ -107,7 +129,7 @@ $(OBJ_PATH)/%.o: %.cpp #Makefile parameters .DEFAULT_GOAL := all -all: build +all: preprocessor build ifeq ($(BUILD), BUILD_STATIC) build: STATIC_LIB @@ -131,9 +153,18 @@ static: api: $(MAKE) -C $(API_PATH) BUILD=$(BUILD) +gamepad_include: + $(MAKE) -C $(GAMEPAD_LIB_PATH) include + +gamepad: + $(MAKE) -C $(GAMEPAD_LIB_PATH) library + +preprocessor: gamepad_include + clean: @rm -rf $(BUILD_PATH) $(MAKE) -C $(API_PATH) $@ + $(MAKE) -C $(GAMEPAD_LIB_PATH) $@ run: @$(BIN) From 7a37ba5abdf4f939e767b9199deddc9d16228ad8 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 13:37:37 +0300 Subject: [PATCH 073/336] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB?= =?UTF-8?q?=D1=8F=D1=86=D0=B8=D1=8F=20=D0=B3=D0=B5=D0=B9=D0=BC=D0=BF=D0=B0?= =?UTF-8?q?=D0=B4-=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=D0=B4=20=D0=9E=D0=A1=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadManager.cpp | 3 ++- code/c++/cxx-gamepad-app/GamepadManager.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp index df6ca7b..5f262f8 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.cpp +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -1,4 +1,5 @@ -#include "TrackPlatform_Manager.h" +#include +#include "TrackPlatform_Manager.h" #include "gamepad/Gamepad.h" #include "gamepad_callbacks.h" diff --git a/code/c++/cxx-gamepad-app/GamepadManager.h b/code/c++/cxx-gamepad-app/GamepadManager.h index 6e736d2..39ca564 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.h +++ b/code/c++/cxx-gamepad-app/GamepadManager.h @@ -12,7 +12,7 @@ class GamepadManager /** * @brief mutex is locked when handler thread is running, else not locked */ - std::atomic_bool isRequireToRun = false; + std::atomic_bool isRequireToRun = {false}; /** * @brief Handler thread pointer */ From 2ce5bfad6ea059961a313b13a08700a574f10e42 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 14:43:26 +0300 Subject: [PATCH 074/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D1=8B=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20WiFi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TCPIP_Connector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/c++/cxx-api/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp index 68a1ef9..5bc6800 100644 --- a/code/c++/cxx-api/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/TCPIP_Connector.cpp @@ -177,6 +177,7 @@ TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) TCPIP_Connector::~TCPIP_Connector() { + sendStopCommand(); TCPIP_Connector::disconnect(); if (addressInfo) { From f956b53ae0befd5cfc0ecb721a7948e6fe35ee8d Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 18:29:29 +0300 Subject: [PATCH 075/336] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D1=81=D1=82=D0=BE=D0=BF-=D1=81=D0=B8?= =?UTF-8?q?=D0=BC=D0=B2=D0=BE=D0=BB=D0=B0=20=D0=BD=D0=B0=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B8=D0=B5=D0=BD=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/CorruptedAnswerException.h | 13 +++++++++++++ code/c++/cxx-api/SerialConnector.cpp | 15 ++++++++++++++- code/c++/cxx-api/trackPlatformAllExceptions.h | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 code/c++/cxx-api/CorruptedAnswerException.h diff --git a/code/c++/cxx-api/CorruptedAnswerException.h b/code/c++/cxx-api/CorruptedAnswerException.h new file mode 100644 index 0000000..11ca20d --- /dev/null +++ b/code/c++/cxx-api/CorruptedAnswerException.h @@ -0,0 +1,13 @@ +#ifndef _CORRUPTED_ANSWER_EXCEPTION_H_ +#define _CORRUPTED_ANSWER_EXCEPTION_H_ +#include "TrackPlatformException.h" + +class CorruptedAnswerException : public TrackPlatformException +{ +public: + explicit CorruptedAnswerException() : TrackPlatformException() + { + } +}; + +#endif /* _CORRUPTED_ANSWER_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index edc9bd4..58e123c 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -1,4 +1,5 @@ #include "SerialConnector.h" +#include "trackPlatformAllExceptions.h" void SerialConnector::write(const std::string& s) { @@ -37,7 +38,19 @@ bool SerialConnector::isConnected() std::string SerialConnector::readOneAnswer() { - return readPort->readline(messageMaxSize, std::string(1, stopSymbol)); + if (!isConnectedToArduino) + { + return ""; + } + + auto text = readPort->readline(messageMaxSize, std::string(1, stopSymbol)); + if (text.back() != stopSymbol) + { + throw CorruptedAnswerException(); + } + + text.pop_back(); + return text; } void SerialConnector::connect() diff --git a/code/c++/cxx-api/trackPlatformAllExceptions.h b/code/c++/cxx-api/trackPlatformAllExceptions.h index 39ad92a..05f4a92 100644 --- a/code/c++/cxx-api/trackPlatformAllExceptions.h +++ b/code/c++/cxx-api/trackPlatformAllExceptions.h @@ -8,5 +8,6 @@ #include "SocketShutdownException.h" #include "SocketSendException.h" #include "SocketReceiveException.h" +#include "CorruptedAnswerException.h" #endif /* _TRACK_PLATFORM_ALL_EXCEPTIONS_H_ */ From cc6b4f71978ae108c4fd7df9c491b7ad5e468dce Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 18:55:24 +0300 Subject: [PATCH 076/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=B0?= =?UTF-8?q?=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B0=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D1=83=D1=81=D0=BF=D0=B5=D1=88=D0=BD=D0=BE=D0=BC=20=D1=83=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?(=D0=B2=20Arduino=20=D0=B8=20cxx-api)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/trackPlatform.ino | 2 + .../cxx-api/CannotConnectToArduinoException.h | 14 + code/c++/cxx-api/NoConnectionException.h | 14 + code/c++/cxx-api/SerialConnector.cpp | 8 +- code/c++/cxx-api/TCPIP_Connector.cpp | 2 +- .../cxx-api/TrackPlatform_BasicConnector.cpp | 44 ++- .../cxx-api/TrackPlatform_BasicConnector.h | 7 +- code/c++/cxx-api/cxx-api.vcxproj | 373 +++++++++--------- code/c++/cxx-api/cxx-api.vcxproj.filters | 283 ++++++------- code/c++/cxx-api/trackPlatformAllExceptions.h | 2 + 10 files changed, 418 insertions(+), 331 deletions(-) create mode 100644 code/c++/cxx-api/CannotConnectToArduinoException.h create mode 100644 code/c++/cxx-api/NoConnectionException.h diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 84a9698..484241a 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -50,6 +50,8 @@ void selectDevice() DEBUG_PRINTLN("USB"); } } + + device->send("OK"); DEBUG_PRINTLN("Arduino found a manager"); } diff --git a/code/c++/cxx-api/CannotConnectToArduinoException.h b/code/c++/cxx-api/CannotConnectToArduinoException.h new file mode 100644 index 0000000..abd54f9 --- /dev/null +++ b/code/c++/cxx-api/CannotConnectToArduinoException.h @@ -0,0 +1,14 @@ +#ifndef _CANNOT_CONNECT_TO_ARDUINO_EXCEPTION_H_ +#define _CANNOT_CONNECT_TO_ARDUINO_EXCEPTION_H_ + +#include "TrackPlatformException.h" + +class CannotConnectToArduinoException : public TrackPlatformException +{ +public: + explicit CannotConnectToArduinoException() : TrackPlatformException() + { + } +}; + +#endif /* _CANNOT_CONNECT_TO_ARDUINO_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/NoConnectionException.h b/code/c++/cxx-api/NoConnectionException.h new file mode 100644 index 0000000..4d03921 --- /dev/null +++ b/code/c++/cxx-api/NoConnectionException.h @@ -0,0 +1,14 @@ +#ifndef _NO_CONNECTION_EXCEPTION_H_ +#define _NO_CONNECTION_EXCEPTION_H_ + +#include "TrackPlatformException.h" + +class NoConnectionException : public TrackPlatformException +{ +public: + explicit NoConnectionException() : TrackPlatformException() + { + } +}; + +#endif /* _NO_CONNECTION_EXCEPTION_H_ */ diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index 58e123c..c0070d6 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -33,14 +33,14 @@ std::string SerialConnector::read() bool SerialConnector::isConnected() { - return (readPort->isOpen() && writePort->isOpen()); + return (TrackPlatform_BasicConnector::isConnected() && readPort->isOpen() && writePort->isOpen()); } std::string SerialConnector::readOneAnswer() { - if (!isConnectedToArduino) + if (!isConnected()) { - return ""; + throw NoConnectionException(); } auto text = readPort->readline(messageMaxSize, std::string(1, stopSymbol)); @@ -48,7 +48,7 @@ std::string SerialConnector::readOneAnswer() { throw CorruptedAnswerException(); } - + text.pop_back(); return text; } diff --git a/code/c++/cxx-api/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp index 5bc6800..edd41fb 100644 --- a/code/c++/cxx-api/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/TCPIP_Connector.cpp @@ -108,7 +108,7 @@ void TCPIP_Connector::closeSocket() bool TCPIP_Connector::isConnected() { - return isConnected_private; + return (TrackPlatform_BasicConnector::isConnected() && isConnected_private); } void TCPIP_Connector::connect() diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index f34e125..e8dd24f 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -1,16 +1,41 @@ -#include "CommandsEnum.h" -#include "TrackPlatform_BasicConnector.h" +#include +#include + #include "Logger.h" +#include "trackPlatformAllExceptions.h" +#include "CommandsEnum.h" + +#include "TrackPlatform_BasicConnector.h" + +const std::string TrackPlatform_BasicConnector::connectedAnswer = "OK"; void TrackPlatform_BasicConnector::sendStartCommand() { std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(startBasicAPI); - sendOneCommand(command); + isConnectedToArduino = true; + for (auto i = 0; i < timesToAutoreconnect; ++i) + { + sendOneCommand(command); + if (readOneAnswer() == connectedAnswer) + { + return; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(timeoutToNextConnectInMs)); + } + + isConnectedToArduino = false; + throw CannotConnectToArduinoException(); } void TrackPlatform_BasicConnector::sendStopCommand() { + if (!isConnected()) + { + throw NoConnectionException(); + } std::string command = std::string() + static_cast(communicationControllerID) + static_cast(stopCommunicationCommand); sendOneCommand(command); + isConnectedToArduino = false; } TrackPlatform_BasicConnector::TrackPlatform_BasicConnector() @@ -23,11 +48,24 @@ TrackPlatform_BasicConnector::~TrackPlatform_BasicConnector() std::string TrackPlatform_BasicConnector::readOneAnswer() { + if (!isConnected()) + { + throw NoConnectionException(); + } return read(); } void TrackPlatform_BasicConnector::sendOneCommand(const std::string& s) { + if (!isConnected()) + { + throw NoConnectionException(); + } write(s + stopSymbol); Logger::log("Send: " + s + stopSymbol); } + +bool TrackPlatform_BasicConnector::isConnected() +{ + return isConnectedToArduino; +} diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index d047730..e420052 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -5,8 +5,13 @@ class TrackPlatform_BasicConnector { + bool isConnectedToArduino = false; + protected: static const char stopSymbol = '|'; + static const uint8_t timesToAutoreconnect = 3; + static const uint32_t timeoutToNextConnectInMs = 100; + static const std::string connectedAnswer; virtual void write(const std::string& s) = 0; virtual std::string read() = 0; @@ -32,7 +37,7 @@ class TrackPlatform_BasicConnector */ virtual std::string readOneAnswer(); virtual void sendOneCommand(const std::string& s); - virtual bool isConnected() = 0; + virtual bool isConnected(); /** * @brief Manual connect if not already connected */ diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index b2b4b13..8c75329 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -1,185 +1,188 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {32D3778A-E59E-4DBC-8D86-BD23B708CA12} - Win32Proj - cxxapi - - - - StaticLibrary - true - v141 - Unicode - - - StaticLibrary - false - v141 - true - Unicode - - - StaticLibrary - true - v141 - Unicode - - - StaticLibrary - false - v141 - true - Unicode - - - - - - - - - - - - - - - - - - - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - $(ProjectDir)serial_support\include\;$(IncludePath) - $(SolutionDir)Output\$(Configuration)-$(Platform)\ - $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - - - - - Level3 - Disabled - _DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - - - - - Level3 - - - MaxSpeed - true - true - NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {32D3778A-E59E-4DBC-8D86-BD23B708CA12} + Win32Proj + cxxapi + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(ProjectDir)serial_support\include\;$(IncludePath) + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 4892540..8ee1d7e 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -1,138 +1,147 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {de9cad78-f264-4652-87a0-7f8536f7ef0c} - - - {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} - - - {a897fa9d-d634-41b6-a441-71b4a660fa92} - - - {09716c3b-089b-4880-b137-c4da5ccc81f8} - - - {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} - - - {8cb6d371-6c98-4f8c-ace2-6e3059467355} - - - {c8707437-f967-4f30-b1b5-cde6082dca67} - - - {20cccc26-6e34-4b3e-8ed5-4d44cbf4c28e} - - - {42cc74a7-2d02-4a96-828e-2b504625d84d} - - - - - Header Files - - - Header Files - - - serial_support\header - - - serial_support\header - - - serial_support\header - - - Header Files - - - Communication\header - - - Communication\header - - - Communication\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions\header - - - exceptions - - - exceptions\header - - - Communication\header - - - Communication - - - Header Files - - - - - Source Files - - - serial_support\source - - - serial_support\source - - - serial_support\source - - - Source Files - - - Communication\source - - - Communication\source - - - exceptions\source - - - Communication\source - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {de9cad78-f264-4652-87a0-7f8536f7ef0c} + + + {7f55ad7e-608f-469d-8efc-4fbaa0e120fd} + + + {a897fa9d-d634-41b6-a441-71b4a660fa92} + + + {09716c3b-089b-4880-b137-c4da5ccc81f8} + + + {619f9cf3-95aa-4cd8-9da7-8054ec8ca353} + + + {8cb6d371-6c98-4f8c-ace2-6e3059467355} + + + {c8707437-f967-4f30-b1b5-cde6082dca67} + + + {20cccc26-6e34-4b3e-8ed5-4d44cbf4c28e} + + + {42cc74a7-2d02-4a96-828e-2b504625d84d} + + + + + Header Files + + + Header Files + + + serial_support\header + + + serial_support\header + + + serial_support\header + + + Header Files + + + Communication\header + + + Communication\header + + + Communication\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + exceptions + + + exceptions\header + + + Communication\header + + + Communication + + + Header Files + + + exceptions\header + + + exceptions\header + + + exceptions\header + + + + + Source Files + + + serial_support\source + + + serial_support\source + + + serial_support\source + + + Source Files + + + Communication\source + + + Communication\source + + + exceptions\source + + + Communication\source + + + Source Files + + \ No newline at end of file diff --git a/code/c++/cxx-api/trackPlatformAllExceptions.h b/code/c++/cxx-api/trackPlatformAllExceptions.h index 05f4a92..a08cdc4 100644 --- a/code/c++/cxx-api/trackPlatformAllExceptions.h +++ b/code/c++/cxx-api/trackPlatformAllExceptions.h @@ -8,6 +8,8 @@ #include "SocketShutdownException.h" #include "SocketSendException.h" #include "SocketReceiveException.h" +#include "CannotConnectToArduinoException.h" #include "CorruptedAnswerException.h" +#include "NoConnectionException.h" #endif /* _TRACK_PLATFORM_ALL_EXCEPTIONS_H_ */ From bbdcb448f34af4ad87c4ab24412c81d19a2f3685 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 19:37:02 +0300 Subject: [PATCH 077/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B2=D1=8B=D0=BB=D0=B5=D1=82=D1=8B?= =?UTF-8?q?=20=D0=B8=D0=B7-=D0=B7=D0=B0=20=D0=B2=D1=8B=D1=85=D0=BE=D0=B4?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B7=D0=B0=20=D0=BF=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D1=8B=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * при разборе строки ответа если пришел пустой ответ; * при разборе строки, которая содержит массив чисел с разделителем и заканчивается числом (без символа-разделителя) --- code/c++/cxx-api/SerialConnector.cpp | 2 +- .../cxx-api/TrackPlatform_BasicManagement.cpp | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/code/c++/cxx-api/SerialConnector.cpp b/code/c++/cxx-api/SerialConnector.cpp index c0070d6..b5c8877 100644 --- a/code/c++/cxx-api/SerialConnector.cpp +++ b/code/c++/cxx-api/SerialConnector.cpp @@ -44,7 +44,7 @@ std::string SerialConnector::readOneAnswer() } auto text = readPort->readline(messageMaxSize, std::string(1, stopSymbol)); - if (text.back() != stopSymbol) + if (!text.length() || text.back() != stopSymbol) { throw CorruptedAnswerException(); } diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 920f0f3..bc0c54f 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -26,19 +26,21 @@ std::vector TrackPlatform_BasicManagement::parseStringToArray(std::str std::vector distancies; size_t stringOldLen = 0; size_t posToNextValue = 0; - do + try { - try + do { + distancies.push_back(std::stoul(s, &posToNextValue)); - } - catch(...) - { - return distancies; - } - stringOldLen = s.length(); - s = s.substr(posToNextValue + sizeof delimiter); - } while ((s != "") && (stringOldLen > s.length())); + stringOldLen = s.length(); + s = s.substr(posToNextValue + sizeof delimiter); + + } while ((s != "") && (stringOldLen > s.length())); + } + catch (...) + { + return distancies; + } if (stringOldLen <= s.length()) { From 30dbd5ce4ba73774eaefd6babb3e9a86afc31317 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 21 Aug 2017 19:38:51 +0300 Subject: [PATCH 078/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BD=D0=B5=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D1=80=D0=B5=D0=B0=D0=BA?= =?UTF-8?q?=D1=86=D0=B8=D1=8F,=20=D0=B5=D1=81=D0=BB=D0=B8=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D1=83=D0=BB=D1=8C=20=D0=BD=D0=B5=20=D0=BE=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=87=D0=B0=D0=B5=D1=82=20=D1=81=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B2=D0=BE=D0=B3=D0=BE=20=D1=80=D0=B0=D0=B7=D0=B0.=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B2=D1=8B=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BE=D1=87=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=BE=20=D0=BF=D0=BE=D0=BF=D1=8B=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D1=85=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicConnector.cpp | 13 +++++++++++-- code/c++/cxx-gamepad-app/main.cpp | 8 +++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index e8dd24f..d9d84e5 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -15,16 +15,25 @@ void TrackPlatform_BasicConnector::sendStartCommand() isConnectedToArduino = true; for (auto i = 0; i < timesToAutoreconnect; ++i) { + Logger::log("Trying to connect to arduino. Attempt " + std::to_string(i + 1)); sendOneCommand(command); - if (readOneAnswer() == connectedAnswer) + try { + if (readOneAnswer() == connectedAnswer) + { + Logger::log("Connected successfully"); + return; + } + } + catch(CorruptedAnswerException&) { - return; + //All is good, module not answered, try again } std::this_thread::sleep_for(std::chrono::milliseconds(timeoutToNextConnectInMs)); } isConnectedToArduino = false; + Logger::log("Cannot connect to arduino"); throw CannotConnectToArduinoException(); } void TrackPlatform_BasicConnector::sendStopCommand() diff --git a/code/c++/cxx-gamepad-app/main.cpp b/code/c++/cxx-gamepad-app/main.cpp index 0b5da24..3ec6ef7 100644 --- a/code/c++/cxx-gamepad-app/main.cpp +++ b/code/c++/cxx-gamepad-app/main.cpp @@ -13,7 +13,9 @@ int main(int argc, char* argv[]) std::cout << "rx = tx = " << rtx << "; baudrate = " << baudrate << std::endl; - Logger::log("Add is running"); + Logger::log("App is running"); + + int retCode = 0; try { @@ -30,10 +32,10 @@ int main(int argc, char* argv[]) { std::cout << "Exception was catched" << std::endl; Logger::log("Exception was catched"); - return 1; + retCode = 1; } Logger::log("App is closed"); - return 0; + return retCode; } From e83a8c376c7c399017734cf6449559df466dd4e6 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Tue, 22 Aug 2017 00:02:59 +0300 Subject: [PATCH 079/336] =?UTF-8?q?=D0=9F=D0=BE=D1=87=D1=82=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D1=8B=D0=B9=20=D1=84=D1=83=D0=BD=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=81=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=86=D0=B8=D0=B5=D0=B9=20,=20=D0=B7=D0=B0=20?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=D0=BC=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8E=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D1=91=D0=BC=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=BE=D1=82=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 259 ++++++++++++++----------------- code/Arduino/connectors/WiFi.h | 49 ++++-- 2 files changed, 154 insertions(+), 154 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index e4786e4..ac74306 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -1,250 +1,225 @@ #include "WiFi.h" -bool WiFi::isInited = false; - WiFi::WiFi(unsigned long speed) : ConnectingDevice(&Serial2) { if (isInited) { return; } - isInited = true; Serial2.begin(speed); - - if (Check()) + if (CheckOnReady()) { ChangeSpeed(speed); } - else - { - Reset(speed); - } } WiFi::~WiFi() { } -bool WiFi::ReturningCommandsOff() +bool WiFi::CheckOnReady() { - try + StartingSend("AT"); + if (ready = (read() == "AT\r\nOK") == ReturningCommandsOff()) { - send("ATE0"); + return ready; } - catch (...) + else { - return false; + Reset(); } - return true; } -String WiFi::VersionCheck() +bool WiFi::ReturningCommandsOff() { - try + StartingSend("ATE0"); + if (CheckOnAnswer()) { - send("AT+GMR"); - return ReturnInfo(); + return true; } - catch (...) + else { - return ""; + FatalError(); } } -String WiFi::CheckIPandMAC() +void WiFi::FatalError() { - try - { - send("AT+CIFSR"); - ReturnCheck(); - return ReturnInfo(); - } - catch (...) - { - return ""; - } + ready = false; } -bool WiFi::ChangeSpeed(unsigned long speed) +bool WiFi::CheckOnAnswer() { - try + if (read() != "\r\nOK") { - send("AT+CIOBAUD=" + String(speed)); - ReturnCheck(); + return true; } - catch (...) + else { - return false; + FatalError(); } - return true; } bool WiFi::Reset() { - send("AT+RST"); + StartingSend("AT+RST"); if (ready = (read() == "AT+RST\r\nOK") == ReturningCommandsOff()) { return ready; } else { - return; + FatalError(); } } bool WiFi::Reset(unsigned long speed) { - ready = Reset(); - ChangeSpeed(speed); - return ready; + if (Reset()) + { + ChangeSpeed(speed); + } } -bool WiFi::CreateCurrentHost(String name, String password, int port) +bool WiFi::ChangeSpeed(unsigned long speed) +{ + send("AT+CIOBAUD=" + String(speed)); + CheckOnAnswer(); +} + +String WiFi::VersionCheck() +{ + send("AT+GMR"); + return ReturnInfo(); +} + +String WiFi::ReturnInfo() { - try + String str = read(); + if (int a = str.indexOf("\r\nOK")) { - Open(); - ReturnCheck(); - send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); - ReturnCheck(); - UseTCP(port); + return str.substring(0, a); } - catch (...) + else { - return false; + FatalError(); } - return true; +} + +String WiFi::CheckIPandMAC() +{ + send("AT+CIFSR"); + CheckOnAnswer(); + return ReturnInfo(); +} + +bool WiFi::CreateCurrentHost(String name, String password, int port) +{ + Open(); + CheckOnAnswer(); + send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); + CheckOnAnswer(); + UseTCP(port); } bool WiFi::CreateStaticHost(String name, String password, int port) { - try - { - Open(); - ReturnCheck(); - send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); - ReturnCheck(); - UseTCP(port); - } - catch (...) - { - return false; - } - return true; + Open(); + CheckOnAnswer(); + send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); + CheckOnAnswer(); + UseTCP(port); +} + +bool WiFi::Open() +{ + send("AT+CWMODE_CUR=2"); + CheckOnAnswer(); + opened = true; } String WiFi::NetsList() { - try - { - if (opened) - { - Close(); - } - send("AT+CWLAP"); - return ReturnInfo(); - } - catch (...) - { - return ""; - } + Close(); + send("AT+CWLAP"); + return ReturnInfo(); } bool WiFi::Close() { - try - { - send("AT+CWMODE_CUR=1"); - ReturnCheck(); - opened = false; - } - catch (...) - { - return false; - } - return true; + send("AT+CWMODE_CUR=1"); + CheckOnAnswer(); + opened = false; } -bool WiFi::Open() +bool WiFi::UseTCP(int port) { - try - { - send("AT+CWMODE_CUR=2"); - ReturnCheck(); - opened = true; - } - catch (...) - { - return false; - } - return true; + send("AT+CIPMUX=1"); + CheckOnAnswer(); + send("AT+CIPSERVER=1," + String(port)); + CheckOnAnswer(); } -bool WiFi::UseTCP(int port) +void WiFi::StartingSend(String command) { - try - { - send("AT+CIPMUX=1"); - ReturnCheck(); - send("AT+CIPSERVER=1," + String(port)); - ReturnCheck(); - } - catch (...) - { - return false; - } - return true; + ConnectingDevice::send(command + "\r\n"); } -bool WiFi::Check() +void WiFi::Send(String command) { - send("AT"); - if (ready = (read() == "AT\r\nOK") == ReturningCommandsOff()) + if (ready) { - return ready; + ConnectingDevice::send(command + "\r\n"); } else { - Reset(); + FatalError(); } } -void WiFi::ReturnCheck() +String WiFi::Scan() { - if (read() != "\r\nOK") - { - throw 1; - } + delay(100); + return ConnectingDevice::read(); } -String WiFi::ReturnInfo() +String WiFi::CheckStatus() { - String str = read(); - if (int a = str.indexOf("\r\nOK")) + String response = ""; + if (isInited) { - return str.substring(0, a); + response += "Inited"; } - else + if (!isInited) { - throw 1; + response += "Not Inited"; } -} - -void WiFi::send(String command) -{ if (ready) { - ConnectingDevice::send(command + "\r\n"); + response += ", Ready"; } - else + if (!ready) + { + response += ", Not Ready"; + } + if (opened) { - throw 1; + response += ", Opened"; } + if (!opened) + { + response += ", Closed"; + } + return response; } -String WiFi::read() +String WiFi::Write(String message) { - delay(100); - return ConnectingDevice::read(); + +} + +String WiFi::Read() +{ + } \ No newline at end of file diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 6d67739..99a1537 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -3,11 +3,6 @@ class WiFi : public ConnectingDevice { - /** - * @brief Block for double initialization - */ - static bool isInited; - public: explicit WiFi(unsigned long speed); ~WiFi(); @@ -58,13 +53,13 @@ class WiFi : public ConnectingDevice * @brief * @return */ - virtual void ReturnCheck(); + virtual bool CheckOnAnswer(); /** * @brief * @return */ - virtual bool Check(); + virtual bool CheckOnReady(); /** * @brief @@ -95,14 +90,19 @@ class WiFi : public ConnectingDevice virtual bool CreateStaticHost(String name, String password, int port); /** - * @brief , "\r\n" + * @brief , "\r\n" + */ + virtual void StartingSend(String command); + + /** + * @brief , "\r\n" */ - void send(String command) override; + virtual void Send(String command); /** - * @brief , + * @brief , */ - String read() override; + virtual String Scan(); /** * @brief @@ -110,8 +110,33 @@ class WiFi : public ConnectingDevice */ virtual String ReturnInfo(); + /** + * @brief + */ + virtual void FatalError(); + + /** + * @brief + */ + virtual String Write(String message); + + /** + * @brief + */ + virtual String Read(); + + /** + * @brief + */ + virtual String CheckStatus(); + + /** + * @brief + */ + bool isInited = false; + private: - + /** * @brief */ From 39612651ad48822074f02dd32f4bae611d27e450 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 22 Aug 2017 12:14:29 +0300 Subject: [PATCH 080/336] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=B4=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20=D1=81=20?= =?UTF-8?q?Wi-Fi=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B5=D0=B9=20=D0=B4=D0=BB=D1=8F=20arduino?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.h | 100 ++++++++++++++++----------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 99a1537..ef15ac2 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "ConnectingDevice.h" class WiFi : public ConnectingDevice @@ -6,144 +6,144 @@ class WiFi : public ConnectingDevice public: explicit WiFi(unsigned long speed); ~WiFi(); - + /** - * @brief + * @brief Убирает посланную команду в возвращаемом от модуля сообщении */ virtual bool ReturningCommandsOff(); /** - * @brief - * @return + * @brief Проверка версии прошивки + * @return Вся информация о версии прошивки модуля */ virtual String VersionCheck(); - + /** - * @brief - * @return + * @brief Выводит список доступных модулю в данный момент сетей для подключения + * @return Строка со списком всех доступных сетей */ virtual String NetsList(); - + /** - * @brief IP MAC - * @return IP MAC + * @brief Получение текущих IP и MAC + * @return Строка с текущими IP и MAC */ virtual String CheckIPandMAC(); /** - * @brief - * @param speed + * @brief Изменяет рабочую скорость модуля + * @param speed Скорость работы модуля */ virtual bool ChangeSpeed(unsigned long speed); - + /** - * @brief - * @return + * @brief Перезапускает модуль + * @return Готовность модуля к работе */ virtual bool Reset(); /** - * @brief - * @param speed - * @return + * @brief Перезапускает модуль + * @param speed Скорость работы модуля + * @return Готовность модуля к работе */ virtual bool Reset(unsigned long speed); - + /** - * @brief - * @return + * @brief Делает проверку на успешность посланной команды + * @return Команда выполнена */ virtual bool CheckOnAnswer(); /** - * @brief - * @return + * @brief Делает первичную проверку модуля + * @return Готовность модуля к работе */ virtual bool CheckOnReady(); - + /** - * @brief + * @brief Переводит модуль в режим клиента */ virtual bool Close(); - + /** - * @brief TCP + * @brief Переводит модуль в режим хоста без TCP */ virtual bool Open(); - + /** - * @brief TCP - * @param + * @brief Включает TCP + * @param Принимает номер порта */ virtual bool UseTCP(int port); - + /** - * @brief - * @param name , password port UseTCP + * @brief Устанавливает параметры хоста без записи в кэш + * @param name имя точки доступа, password пароль и port номер порта для вызова функции UseTCP */ virtual bool CreateCurrentHost(String name, String password, int port); - + /** - * @brief - * @param name , password port UseTCP + * @brief Устанавливает параметры хоста с записью в кэш + * @param name имя точки доступа, password пароль и port номер порта для вызова функции UseTCP */ virtual bool CreateStaticHost(String name, String password, int port); /** - * @brief , "\r\n" + * @brief Функция отправки, добавляющая "\r\n" ко всем командам без проверки статуса модуля */ virtual void StartingSend(String command); - + /** - * @brief , "\r\n" + * @brief Функция отправки, добавляющая "\r\n" ко всем командам и проверяющая статус модуля */ virtual void Send(String command); /** - * @brief , + * @brief Функция приёма ответа с модуля, добавляющая задержку перед получением ответа */ virtual String Scan(); /** - * @brief - * @return + * @brief Преобразует возвращаемую строку + * @return Отфильтрованный ответ */ virtual String ReturnInfo(); /** - * @brief + * @brief Функция выхода при критической ошибке */ virtual void FatalError(); /** - * @brief + * @brief Функция отправки данных пользователю */ virtual String Write(String message); /** - * @brief + * @brief Функция приёма данных от пользователя */ virtual String Read(); /** - * @brief + * @brief Функция выхода при критической ошибке */ virtual String CheckStatus(); /** - * @brief + * @brief Индикатор проведённой инициализации модуля */ bool isInited = false; private: /** - * @brief + * @brief Индикатор готовности модуля к работе */ bool ready = false; /** - * @brief / + * @brief Индикатор состояния модуля клиент/хост */ bool opened = false; }; \ No newline at end of file From b6947235d3d4bb9960db87f24fbc385546631441 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 23 Aug 2017 21:43:22 +0300 Subject: [PATCH 081/336] Linux compilation fix --- code/c++/cxx-api/TrackPlatform_BasicConnector.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index d9d84e5..7100d14 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -7,6 +7,9 @@ #include "TrackPlatform_BasicConnector.h" +const char TrackPlatform_BasicConnector::stopSymbol; +const uint8_t TrackPlatform_BasicConnector::timesToAutoreconnect; +const uint32_t TrackPlatform_BasicConnector::timeoutToNextConnectInMs; const std::string TrackPlatform_BasicConnector::connectedAnswer = "OK"; void TrackPlatform_BasicConnector::sendStartCommand() From 772aa07691961edf622aae570972c494c373f037 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 23 Aug 2017 22:45:21 +0300 Subject: [PATCH 082/336] =?UTF-8?q?cxx-app=20=D0=B0=D0=B4=D0=B0=D0=BF?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20Wi-fi=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=D0=BC.=20=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D0=B2=D1=8B=D0=B1?= =?UTF-8?q?=D0=B8=D1=80=D0=B0=D1=82=D1=8C=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=87=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B7=20=D0=BE=D0=B4=D0=B8=D0=BD=20#if?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/main.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 60a0869..0b0affe 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -15,6 +15,9 @@ int main(int argc, char* argv[]) std::string rx = "COM13", tx = "COM13"; uint32_t baudrate = 9600U; + std::string ip = "192.168.4.1"; + uint16_t port = 1001; + /*std::cout << "rx" << std::endl; std::cin >> rx; std::cout << "tx" << std::endl; @@ -22,15 +25,23 @@ int main(int argc, char* argv[]) std::cout << "baudrate" << std::endl; std::cin >> baudrate; */ - std::cout << "rx = " << rx << " tx = " << tx << " baudrate = " << baudrate << std::endl; + std::cout << "rx = " << rx << " tx = " << tx << " baudrate = " << baudrate << " ip = " << ip << " port = " << port << std::endl; try { CommunicationInfoStruct info; +#if 0 info.SerialInfo.rxPort = rx; info.SerialInfo.txPort = tx; info.SerialInfo.baudrate = baudrate; TrackPlatform_Manager trackPlatform(bluetooth, info); + +#else + info.TCPIPInfo.ip = ip; + info.TCPIPInfo.port = port; + TrackPlatform_Manager trackPlatform(WiFi, info); +#endif + bool isExit = false; while (!isExit) { From 6bfc370faa2f0af6625c67135dd2ae921b60a395 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 23 Aug 2017 23:05:22 +0300 Subject: [PATCH 083/336] =?UTF-8?q?=D0=92=20cxx-api=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20Wi-Fi.=20=D0=A2=D0=B5?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BF=D1=80=D0=BE=D0=B8=D1=81=D1=85?= =?UTF-8?q?=D0=BE=D0=B4=D0=B8=D1=82=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BD=D0=BE=D0=B5=20=D1=87=D1=82=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BE=D0=BE?= =?UTF-8?q?=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20(=D1=83=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=D1=8B=20=D0=BC=D0=B5=D1=82=D0=B0=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5),=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=81=20=D1=80=D0=BE=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=BC=20=D0=B8=20=D0=BE=D1=82=D1=81=D0=BE=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=82=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=B3=D0=BE=20(=D0=B2=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8=D0=B8=20=D1=81=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=BB=D0=BE=D0=BC).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TCPIP_Connector.cpp | 102 ++++++++++++++++++--------- code/c++/cxx-api/TCPIP_Connector.h | 6 +- 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/code/c++/cxx-api/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp index edd41fb..056f354 100644 --- a/code/c++/cxx-api/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/TCPIP_Connector.cpp @@ -79,6 +79,56 @@ std::string TCPIP_Connector::read() return answer; } +bool TCPIP_Connector::connectSocket() +{ + if (isSocketConnected) { + return false; + } + + // Attempt to connect to the first address returned by + // the call to getaddrinfo + struct addrinfo* ptr = addressInfo; + + // Create a SOCKET for connecting to server + connectedSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + + if (connectedSocket == INVALID_SOCKET) { + throw SocketException(WSAGetLastError()); + } + + // Connect to server. +#ifdef _WIN32 + int iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); +#else /* _WIN32 */ + int iResult = ::connect(connectedSocket, addressInfo->ai_addr, addressInfo->ai_addrlen); +#endif /* _WIN32 */ + if (iResult == SOCKET_ERROR) { + closeSocket(); + return false; + } + + isSocketConnected = true; + return true; +} + +bool TCPIP_Connector::disconnectSocket() +{ + if (!isSocketConnected) + { + return false; + } + + // shutdown the sending and recieving data by socket + int iResult = shutdown(connectedSocket, SD_BOTH); + if (iResult == SOCKET_ERROR) { + throw SocketShutdownException(WSAGetLastError()); + } + + closeSocket(); + isSocketConnected = false; + return true; +} + void TCPIP_Connector::configureSocket() { struct addrinfo hints; @@ -108,56 +158,39 @@ void TCPIP_Connector::closeSocket() bool TCPIP_Connector::isConnected() { - return (TrackPlatform_BasicConnector::isConnected() && isConnected_private); + return (TrackPlatform_BasicConnector::isConnected() && isSocketConnected); } void TCPIP_Connector::connect() { - if (isConnected_private) { - return; + if (connectSocket()) + { + sendStartCommand(); } +} - // Attempt to connect to the first address returned by - // the call to getaddrinfo - struct addrinfo* ptr = addressInfo; - - // Create a SOCKET for connecting to server - connectedSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); - - if (connectedSocket == INVALID_SOCKET) { - throw SocketException(WSAGetLastError()); - } +std::string TCPIP_Connector::readOneAnswer() +{ + auto answer = TrackPlatform_BasicConnector::readOneAnswer(); - // Connect to server. -#ifdef _WIN32 - int iResult = ::connect(connectedSocket, addressInfo->ai_addr, static_cast(addressInfo->ai_addrlen)); -#else /* _WIN32 */ - int iResult = ::connect(connectedSocket, addressInfo->ai_addr, addressInfo->ai_addrlen); -#endif /* _WIN32 */ - if (iResult == SOCKET_ERROR) { - closeSocket(); - } - else + if (answer.length() == 0 || answer.back() != stopSymbol) { - isConnected_private = true; + throw CorruptedAnswerException(); } + + answer.pop_back(); + return answer; } void TCPIP_Connector::disconnect() { - if (!isConnected_private) + //if api is connected to arduino + if (isConnected()) { - return; - } - - // shutdown the sending and recieving data by socket - int iResult = shutdown(connectedSocket, SD_BOTH); - if (iResult == SOCKET_ERROR) { - throw SocketShutdownException(WSAGetLastError()); + sendStopCommand(); } - closeSocket(); - isConnected_private = false; + disconnectSocket(); } TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) @@ -177,7 +210,6 @@ TCPIP_Connector::TCPIP_Connector(const std::string& ip, uint16_t port) TCPIP_Connector::~TCPIP_Connector() { - sendStopCommand(); TCPIP_Connector::disconnect(); if (addressInfo) { diff --git a/code/c++/cxx-api/TCPIP_Connector.h b/code/c++/cxx-api/TCPIP_Connector.h index 019703f..dcbb20c 100644 --- a/code/c++/cxx-api/TCPIP_Connector.h +++ b/code/c++/cxx-api/TCPIP_Connector.h @@ -40,7 +40,7 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector struct addrinfo *addressInfo = nullptr; SOCKET connectedSocket = INVALID_SOCKET; - bool isConnected_private = false; + bool isSocketConnected = false; void configureSocket(); void closeSocket(); @@ -49,6 +49,9 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector void write(const std::string& s) override; std::string read() override; + bool connectSocket(); + bool disconnectSocket(); + public: /** * @brief Create TCP/IP connector to trackPlatform @@ -63,6 +66,7 @@ class TCPIP_Connector : public TrackPlatform_BasicConnector bool isConnected() override; void connect() override; + std::string readOneAnswer() override; void disconnect() override; }; From 821dc0d9967c062ec0bc7cdf9a5bb559e5ab2fc9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 26 Aug 2017 20:23:15 +0300 Subject: [PATCH 084/336] cxx-app: movement fix --- code/c++/cxx-app/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 0b0affe..c2ec410 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -72,10 +72,10 @@ int main(int argc, char* argv[]) case 'w': trackPlatform.moveForward(); break; - case 'a': + case 's': trackPlatform.moveBackward(); break; - case 's': + case 'a': trackPlatform.rotateAntiClockwise(); break; case 'd': From 11b40bc00285c4432cb105150033c9da56401909 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 26 Aug 2017 22:30:48 +0300 Subject: [PATCH 085/336] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=D0=BC=D0=B8=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../peripheral/ConnectionController.cpp | 77 +++++++++++++++++++ .../Arduino/peripheral/ConnectionController.h | 24 ++++++ code/Arduino/trackPlatform.ino | 65 ++-------------- 3 files changed, 106 insertions(+), 60 deletions(-) create mode 100644 code/Arduino/peripheral/ConnectionController.cpp create mode 100644 code/Arduino/peripheral/ConnectionController.h diff --git a/code/Arduino/peripheral/ConnectionController.cpp b/code/Arduino/peripheral/ConnectionController.cpp new file mode 100644 index 0000000..e658fe2 --- /dev/null +++ b/code/Arduino/peripheral/ConnectionController.cpp @@ -0,0 +1,77 @@ +#include "../Constants.h" +#include "../CommandsEnum.h" +#include "../connectors/DebugSerial.h" + +#include "ConnectionController.h" + +const char ConnectionController::connectCommand[] = { communicationControllerID, startCommunicationCommand, startBasicAPI, 0 }; +const char ConnectionController::disconnectCommand[] = { communicationControllerID, stopCommunicationCommand, 0 }; + +ConnectionController::ConnectionController() +{ + usb = new USB(Constants::usb_serial_speed); + wifi = new WiFi(Constants::wifi_serial_speed); + bluetooth = new Bluetooth(Constants::bluetooth_serial_speed); +} + +void ConnectionController::waitForConnection() +{ + DEBUG_PRINTLN("Arduino tries to found a manager"); + while (!isConnected) { + if (bluetooth->isActive() && bluetooth->read() == connectCommand) { + isConnected = true; + device = bluetooth; + DEBUG_PRINTLN("Bluetooth"); + } + else if (wifi->isActive()) { + isConnected = true; + device = wifi; + DEBUG_PRINTLN("Wifi"); + } + else if (usb->isActive()) { + isConnected = true; + device = usb; + DEBUG_PRINTLN("USB"); + } + } + + device->send("OK"); + DEBUG_PRINTLN("Arduino found a manager"); +} + +ConnectingDevice* ConnectionController::getDevice() const +{ + return device; +} + +String ConnectionController::getCommand() +{ + if (!isConnected) + { + return ""; + } + + String command; + do + { + while (!device->isActive()) + { + delay(1); + } + + command = device->read(); + + //debug + DEBUG_PRINT("Command: "); + DEBUG_PRINTLNHEX(command); + + if (command != disconnectCommand) + { + break; + } + + isConnected = false; + waitForConnection(); + } while (true); + return command; +} diff --git a/code/Arduino/peripheral/ConnectionController.h b/code/Arduino/peripheral/ConnectionController.h new file mode 100644 index 0000000..5c6c7b9 --- /dev/null +++ b/code/Arduino/peripheral/ConnectionController.h @@ -0,0 +1,24 @@ +#pragma once +#include "../connectors/USB.h" +#include "../connectors/Bluetooth.h" +#include "../connectors/WiFi.h" + +class ConnectionController +{ + USB* usb = nullptr; + Bluetooth* bluetooth = nullptr; + WiFi* wifi = nullptr; + ConnectingDevice *device = nullptr; + + static const char connectCommand[]; + static const char disconnectCommand[]; + + bool isConnected = false; + +public: + ConnectionController(); + + void waitForConnection(); + ConnectingDevice* getDevice() const; + String getCommand(); +}; diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index 484241a..eb135e4 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -1,11 +1,7 @@ -#include "Constants.h" -#include "connectors/WiFi.h" #include "connectors/ConnectingDevice.h" -#include "connectors/Bluetooth.h" #include "CommandsController.h" -#include "connectors/USB.h" #include "connectors/DebugSerial.h" -#include "CommandsEnum.h" +#include "peripheral/ConnectionController.h" #define DIOD_DEBUG @@ -20,77 +16,26 @@ void off45(); #endif /* DIOD_DEBUG */ Constants constants; -Bluetooth* bluetooth = nullptr; -WiFi* wifi = nullptr; -USB* usb = nullptr; -ConnectingDevice *device = nullptr; +ConnectionController* connector; CommandsController* controller = nullptr; -char connectCommand[] = { communicationControllerID, startCommunicationCommand, startBasicAPI, 0 }; -char disconnectCommand[] = { communicationControllerID, stopCommunicationCommand, 0 }; - -void selectDevice() -{ - bool connected = false; - DEBUG_PRINTLN("Arduino tries to found a manager"); - while (!connected) { - if (bluetooth->isActive() && bluetooth->read() == connectCommand) { - connected = true; - device = bluetooth; - DEBUG_PRINTLN("Bluetooth"); - } - else if (wifi->isActive() && wifi->read() == connectCommand) { - connected = true; - device = wifi; - DEBUG_PRINTLN("Wifi"); - } - else if (usb->isActive() && usb->read() == connectCommand) { - connected = true; - device = usb; - DEBUG_PRINTLN("USB"); - } - } - - device->send("OK"); - DEBUG_PRINTLN("Arduino found a manager"); -} - void setup() { #ifdef DIOD_DEBUG diodInit(); #endif /* DIOD_DEBUG */ - usb = new USB(Constants::usb_serial_speed); - wifi = new WiFi(Constants::wifi_serial_speed); - bluetooth = new Bluetooth(Constants::bluetooth_serial_speed); controller = new CommandsController(); + connector = new ConnectionController(); DEBUG_PRINTLN("Arduino was started"); - selectDevice(); + connector->waitForConnection(); } void loop() { - while (device->isActive()) - { - String command = device->read(); - - //debug - DEBUG_PRINT("Command: "); - DEBUG_PRINTLNHEX(command); - - if (command == disconnectCommand) - { - selectDevice(); - } - else - { - controller->handle(device, command); - } - } - delay(1); //for sending commands from mobile (not required) + controller->handle(connector->getDevice(), connector->getCommand()); } #ifdef DIOD_DEBUG From 9e853a6b5644a4e218a17c4172dbe6219abb1656 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 26 Aug 2017 23:50:47 +0300 Subject: [PATCH 086/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=81=D0=BE=D0=B2=D0=BC=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C=20=D1=81=20API=20v2.=20?= =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B4=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D0=BE=D1=80=20(=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B2=D1=81=D1=8F=D0=BA=D0=B8=D0=B9=20=D1=81=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B0=D0=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/CommandsEnum.h | 5 +- .../peripheral/ConnectionController.cpp | 83 ++++++++++++++++--- .../Arduino/peripheral/ConnectionController.h | 5 ++ code/Arduino/trackPlatform.vcxproj | 2 + code/Arduino/trackPlatform.vcxproj.filters | 6 ++ 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/code/Arduino/CommandsEnum.h b/code/Arduino/CommandsEnum.h index f781da2..ded6a71 100644 --- a/code/Arduino/CommandsEnum.h +++ b/code/Arduino/CommandsEnum.h @@ -52,10 +52,13 @@ enum CommunicationCommands { /** * @brief Describes trackPlatform API to working - * @warning Each API must be described in DeviceManager handler + * @see https://github.com/Lipotam/trackPlatform/wiki/Api + * @warning Each API must be described in @ConnectionController handler + * @warning If you add new version for API, check @ConnectionController::highestAPI field */ enum StartCommands { startBasicAPI = 1, //default API v1 + APIWithAnswer = 2, //API v2 }; #endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/Arduino/peripheral/ConnectionController.cpp b/code/Arduino/peripheral/ConnectionController.cpp index e658fe2..5bbefe1 100644 --- a/code/Arduino/peripheral/ConnectionController.cpp +++ b/code/Arduino/peripheral/ConnectionController.cpp @@ -4,38 +4,93 @@ #include "ConnectionController.h" -const char ConnectionController::connectCommand[] = { communicationControllerID, startCommunicationCommand, startBasicAPI, 0 }; +const char ConnectionController::connectCommand[] = { communicationControllerID, startCommunicationCommand, 0 }; const char ConnectionController::disconnectCommand[] = { communicationControllerID, stopCommunicationCommand, 0 }; -ConnectionController::ConnectionController() +ConnectionController::ConnectionController() : connectedAPIversion(startBasicAPI) { usb = new USB(Constants::usb_serial_speed); wifi = new WiFi(Constants::wifi_serial_speed); bluetooth = new Bluetooth(Constants::bluetooth_serial_speed); } +ConnectionController::~ConnectionController() +{ + if (usb) + { + delete usb; + } + if (wifi) + { + delete wifi; + } + if (bluetooth) + { + delete bluetooth; + } +} + void ConnectionController::waitForConnection() { DEBUG_PRINTLN("Arduino tries to found a manager"); + while (!isConnected) { - if (bluetooth->isActive() && bluetooth->read() == connectCommand) { - isConnected = true; + //waiting some info + while (!bluetooth->isActive() && !usb->isActive() && !wifi->isActive()) + { + delay(1); + } + + DEBUG_PRINTLN("Info was found"); + + //reading info + if (bluetooth->isActive()) { device = bluetooth; - DEBUG_PRINTLN("Bluetooth"); + DEBUG_PRINTLN("Bluetooth sends something"); } else if (wifi->isActive()) { - isConnected = true; - device = wifi; - DEBUG_PRINTLN("Wifi"); + device = wifi; + DEBUG_PRINTLN("Wifi sends something"); } else if (usb->isActive()) { - isConnected = true; device = usb; - DEBUG_PRINTLN("USB"); + DEBUG_PRINTLN("USB sends something"); } + + String readInfo = device->read(); + + //check first part of command (if that command is connection command) + if (readInfo.length() < sizeof (connectCommand) || (readInfo.substring(0, sizeof(connectCommand) - 1) != connectCommand)) + { + DEBUG_PRINTLN("Bad info"); + continue; + } + + readInfo = readInfo.substring(sizeof(connectCommand) - 1); + + //check API version length + if (readInfo.length() != 1) + { + DEBUG_PRINTF("Bad API version. Version was very long: %d symbols\n", readInfo.length()); + continue; + } + + //check API version + connectedAPIversion = static_cast(readInfo[0]); + if (connectedAPIversion > highestAPI || connectedAPIversion < lowestAPI) + { + DEBUG_PRINTF("Bad API version. Was %d, required in [%d, %d] interval\n", connectedAPIversion, lowestAPI, highestAPI); + continue; + } + DEBUG_PRINTF("Connected API version: %d\n", connectedAPIversion); + isConnected = true; } - device->send("OK"); + //API v1 & v2 compatibility + if (connectedAPIversion >= APIWithAnswer) + { + device->send("OK"); + } DEBUG_PRINTLN("Arduino found a manager"); } @@ -61,6 +116,12 @@ String ConnectionController::getCommand() command = device->read(); + //API v1 & v2 compatibility + if (connectedAPIversion >= APIWithAnswer) + { + device->send("OK"); + } + //debug DEBUG_PRINT("Command: "); DEBUG_PRINTLNHEX(command); diff --git a/code/Arduino/peripheral/ConnectionController.h b/code/Arduino/peripheral/ConnectionController.h index 5c6c7b9..1762a14 100644 --- a/code/Arduino/peripheral/ConnectionController.h +++ b/code/Arduino/peripheral/ConnectionController.h @@ -2,6 +2,7 @@ #include "../connectors/USB.h" #include "../connectors/Bluetooth.h" #include "../connectors/WiFi.h" +#include "../CommandsEnum.h" class ConnectionController { @@ -12,11 +13,15 @@ class ConnectionController static const char connectCommand[]; static const char disconnectCommand[]; + static const StartCommands lowestAPI = startBasicAPI; + static const StartCommands highestAPI = APIWithAnswer; bool isConnected = false; + StartCommands connectedAPIversion; public: ConnectionController(); + ~ConnectionController(); void waitForConnection(); ConnectingDevice* getDevice() const; diff --git a/code/Arduino/trackPlatform.vcxproj b/code/Arduino/trackPlatform.vcxproj index 67a6a42..4ec9ad7 100644 --- a/code/Arduino/trackPlatform.vcxproj +++ b/code/Arduino/trackPlatform.vcxproj @@ -92,6 +92,7 @@ + @@ -109,6 +110,7 @@ + diff --git a/code/Arduino/trackPlatform.vcxproj.filters b/code/Arduino/trackPlatform.vcxproj.filters index 4d322cd..b43e0c7 100644 --- a/code/Arduino/trackPlatform.vcxproj.filters +++ b/code/Arduino/trackPlatform.vcxproj.filters @@ -99,6 +99,9 @@ utils\header + + peripheral\header + @@ -137,6 +140,9 @@ utils\source + + peripheral\source + From de1baa650dcaf7bcd6662a5cc9b27ed3c7e3ca89 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 27 Aug 2017 09:02:40 +0300 Subject: [PATCH 087/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=B1=D0=B0=D0=B3=20=D1=81=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=BE=D0=B9=20=D0=BE=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D0=B0=20=D0=BD=D0=B0=20=D0=BD=D0=BE=D0=B2=D0=BE?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D1=83=D1=81=D1=82=D1=80=D0=BE=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=BE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/trackPlatform.ino | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/Arduino/trackPlatform.ino b/code/Arduino/trackPlatform.ino index eb135e4..bf31364 100644 --- a/code/Arduino/trackPlatform.ino +++ b/code/Arduino/trackPlatform.ino @@ -35,7 +35,15 @@ void setup() void loop() { - controller->handle(connector->getDevice(), connector->getCommand()); + auto command = connector->getCommand(); + if (command.length() >= 2) + { + controller->handle(connector->getDevice(), command); + } + else + { + DEBUG_PRINTLN("Command is short"); + } } #ifdef DIOD_DEBUG From 3ed0870c88d34f28ba8641b47307a3fd93d84756 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 27 Aug 2017 12:01:39 +0300 Subject: [PATCH 088/336] =?UTF-8?q?Submodules=20=D1=82=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D1=83?= =?UTF-8?q?=D1=8E=D1=82=20https=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20ssh=20(=D1=82.=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D1=82=D1=80=D0=B5=D0=B1=D1=83=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=8F=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=B8=D1=82=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D0=B5=D0=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index b712e71..fcadad9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "cxx_serial_support"] path = code/c++/cxx-api/serial_support - url = git@github.com:wjwwood/serial.git + url = https://github.com/wjwwood/serial.git [submodule "cxx_gamepad_support"] path = code/c++/cxx-gamepad-app/gamepad_support -url=git@github.com:AJIOB/libstem_gamepad.git \ No newline at end of file + url = https://github.com/AJIOB/libstem_gamepad.git From 27e76f6859e864635fa56ce3643b619ea01c9d07 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 27 Aug 2017 13:44:54 +0300 Subject: [PATCH 089/336] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D0=BB=D0=B5=D1=80=20=D1=81=D0=B5=D0=BD=D1=81=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B2=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=B8=D0=B8=20=D1=81=20=D0=BE=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B8=D0=B5=D0=BC=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/peripheral/SensorsController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Arduino/peripheral/SensorsController.cpp b/code/Arduino/peripheral/SensorsController.cpp index 5dce183..6761d50 100644 --- a/code/Arduino/peripheral/SensorsController.cpp +++ b/code/Arduino/peripheral/SensorsController.cpp @@ -135,7 +135,7 @@ int SensorsController::getDistance(int number) { if (volts == 0) { DEBUG_PRINTLN("Distance volts were 0"); - return 0; + return -1; } float distance = (6762 / (volts)) - 4; DEBUG_PRINTF("Distance volts = %d, dist * 10000 = %06ld\n", (int)volts, (long)(distance * 10000)); From b1894d9d7c0042e32093c23a094f82284041b5fa Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 27 Aug 2017 14:07:41 +0300 Subject: [PATCH 090/336] =?UTF-8?q?=D0=A3=D0=B2=D0=B5=D0=BB=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=B2=D1=80=D0=B5=D0=BC=D1=8F=20=D0=BE?= =?UTF-8?q?=D0=B6=D0=B8=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0=D0=BD=D0=B8=D1=8E,=20?= =?UTF-8?q?=D1=82.=D0=BA.=20=D0=B5=D1=81=D0=BB=D0=B8=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D1=8F=D1=82=D1=8C=D1=81?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=20USB=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20?= =?UTF-8?q?=D1=82=D0=BE=D0=B3=D0=BE,=20=D0=BA=D0=B0=D0=BA=20=D1=83=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=BE=20=D0=B1=D1=8B?= =?UTF-8?q?=D0=BB=D0=BE=20=D0=BE=D0=B1=D0=B5=D1=81=D1=82=D0=BE=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE,=20=D0=BE=D0=BD=D0=BE=20=D0=BD=D0=B0=D1=87=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0=D0=B5=D1=82=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B7=D0=B0?= =?UTF-8?q?=D1=82=D0=B3=D1=83=D0=B6=D0=B0=D1=82=D1=8C=D1=81=D1=8F=20=D0=B8?= =?UTF-8?q?=20=D0=BD=D0=B5=20=D1=83=D0=B4=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20?= =?UTF-8?q?=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=B8=D1=82=D1=8C=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicConnector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index e420052..68f189f 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -10,7 +10,7 @@ class TrackPlatform_BasicConnector protected: static const char stopSymbol = '|'; static const uint8_t timesToAutoreconnect = 3; - static const uint32_t timeoutToNextConnectInMs = 100; + static const uint32_t timeoutToNextConnectInMs = 500; static const std::string connectedAnswer; virtual void write(const std::string& s) = 0; From 96edded61b898f1713e336bc1fd35d7004af035d Mon Sep 17 00:00:00 2001 From: Kimentii Date: Sun, 27 Aug 2017 15:30:30 +0300 Subject: [PATCH 091/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=81=D0=B5=D0=B2=D0=B4=D0=BE=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D1=84=D0=B8=D0=BA=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/SensorsViewer.cpp | 28 ++++++++++++++++++++++++ code/c++/cxx-app/SensorsViewer.h | 18 +++++++++++++++ code/c++/cxx-app/cxx-app.vcxproj | 4 ++++ code/c++/cxx-app/cxx-app.vcxproj.filters | 8 +++++++ code/c++/cxx-app/main.cpp | 19 ++++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 code/c++/cxx-app/SensorsViewer.cpp create mode 100644 code/c++/cxx-app/SensorsViewer.h diff --git a/code/c++/cxx-app/SensorsViewer.cpp b/code/c++/cxx-app/SensorsViewer.cpp new file mode 100644 index 0000000..354edc6 --- /dev/null +++ b/code/c++/cxx-app/SensorsViewer.cpp @@ -0,0 +1,28 @@ +#include "SensorsViewer.h" + + void SensorsViewer::setData(const std::vector& d, SensorType t) { + data = d; + type = t; + } + + void SensorsViewer::show() { + if (type == LINE_SENSORS) { + if (!data.empty()) { + std::cout << "\r" << "|"; + for (int i = 0; i < data.size(); i++) { + std::cout << (data[i] ? "@@@" : " "); + } + std::cout << "|"; + } + } + else { + if (!data.empty()) { + if (system("clear")) system("cls"); + if (data.size() >= 1) std::cout << " " << std::setw(4) << data[0] << std::endl; + if (data.size() >= 2) std::cout << " " << std::setw(4) << data[1] << (data.size() == 2 ? "\n" : ""); + if (data.size() >= 3) std::cout << " " << std::setw(4) << data[2] << std::endl; + if (data.size() >= 4) std::cout << " " << std::setw(4) << data[3] << (data.size() == 4 ? "\n" : ""); + if (data.size() >= 5) std::cout << " " << std::setw(4) << data[4] << std::endl; + } + } + } \ No newline at end of file diff --git a/code/c++/cxx-app/SensorsViewer.h b/code/c++/cxx-app/SensorsViewer.h new file mode 100644 index 0000000..979afdb --- /dev/null +++ b/code/c++/cxx-app/SensorsViewer.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include +#include + +enum SensorType { + LINE_SENSORS, DISTANCE_SENSORS +}; + +class SensorsViewer { + std::vector data; + SensorType type; + +public: + void setData(const std::vector& d, SensorType t); + void show(); +}; \ No newline at end of file diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 6c8eb23..32a43a6 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -167,6 +167,10 @@ + + + + diff --git a/code/c++/cxx-app/cxx-app.vcxproj.filters b/code/c++/cxx-app/cxx-app.vcxproj.filters index 0d8d9e4..823c170 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj.filters +++ b/code/c++/cxx-app/cxx-app.vcxproj.filters @@ -18,5 +18,13 @@ Source Files + + Source Files + + + + + Header Files + \ No newline at end of file diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index c2ec410..5346f97 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -9,6 +9,7 @@ #endif #include "TrackPlatform_Manager.h" +#include "SensorsViewer.h" int main(int argc, char* argv[]) { @@ -61,8 +62,10 @@ int main(int argc, char* argv[]) std::cout << " : stop" << std::endl; std::cout << "r: get all line values" << std::endl; std::cout << "e: get fixed line value" << std::endl; + std::cout << "u: show line sensors" << std::endl; std::cout << "t: get all distance values" << std::endl; std::cout << "y: get fixed distance value" << std::endl; + std::cout << "i: show distance sensors" << std::endl; std::cout << "g: set horisontal servo angle in degree" << std::endl; std::cout << "h: set vertical servo angle in degree" << std::endl; break; @@ -101,6 +104,14 @@ int main(int argc, char* argv[]) std::cout << "Value: " << trackPlatform.sensorLineGetValue(a) << std::endl; break; } + case 'u': + { + SensorsViewer sv; + auto arr = trackPlatform.sensorLineGetAllValues(); + sv.setData(arr, LINE_SENSORS); + std::cout << std::endl; + sv.show(); + } case 't': { auto arr = trackPlatform.sensorDistanceGetAllValues(); @@ -118,6 +129,14 @@ int main(int argc, char* argv[]) std::cout << "Value: " << trackPlatform.sensorDistanceGetValue(a) << std::endl; break; } + case 'i': + { + SensorsViewer sv; + auto arr = trackPlatform.sensorDistanceGetAllValues(); + sv.setData(arr, DISTANCE_SENSORS); + std::cout << std::endl; + sv.show(); + } case 'g': { std::cout << "Input num: "; From f23000b84f1802cbc22c334de4e7bbb79ce40140 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Sun, 27 Aug 2017 15:40:29 +0300 Subject: [PATCH 092/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D1=81=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8F=D0=BC=D0=B8=20,=20=D0=B0=20=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=D0=B6=D0=B5=20=D0=BC=D0=BE=D0=BD=D0=B8=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BA=D0=BE=D0=BB=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 143 ++++++++++++++++++++++--------- code/Arduino/connectors/WiFi.h | 12 ++- 2 files changed, 111 insertions(+), 44 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index ac74306..c56e214 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -21,7 +21,7 @@ WiFi::~WiFi() bool WiFi::CheckOnReady() { StartingSend("AT"); - if (ready = (read() == "AT\r\nOK") == ReturningCommandsOff()) + if (ready = (Scan() == "AT\r\nOK") == ReturningCommandsOff()) { return ready; } @@ -34,7 +34,7 @@ bool WiFi::CheckOnReady() bool WiFi::ReturningCommandsOff() { StartingSend("ATE0"); - if (CheckOnAnswer()) + if (Scan() == "ATE0\r\nOK") { return true; } @@ -46,12 +46,14 @@ bool WiFi::ReturningCommandsOff() void WiFi::FatalError() { + IDCount = -1; ready = false; + opened = false; } bool WiFi::CheckOnAnswer() { - if (read() != "\r\nOK") + if (Scan() = "\r\nOK") { return true; } @@ -63,8 +65,11 @@ bool WiFi::CheckOnAnswer() bool WiFi::Reset() { + IDCount = -1; + ready = false; + opened = false; StartingSend("AT+RST"); - if (ready = (read() == "AT+RST\r\nOK") == ReturningCommandsOff()) + if (ready = (Scan() == "AT+RST\r\nOK") == ReturningCommandsOff()) { return ready; } @@ -84,19 +89,19 @@ bool WiFi::Reset(unsigned long speed) bool WiFi::ChangeSpeed(unsigned long speed) { - send("AT+CIOBAUD=" + String(speed)); + Send("AT+CIOBAUD=" + String(speed)); CheckOnAnswer(); } String WiFi::VersionCheck() { - send("AT+GMR"); + Send("AT+GMR"); return ReturnInfo(); } String WiFi::ReturnInfo() { - String str = read(); + String str = Scan(); if (int a = str.indexOf("\r\nOK")) { return str.substring(0, a); @@ -109,7 +114,7 @@ String WiFi::ReturnInfo() String WiFi::CheckIPandMAC() { - send("AT+CIFSR"); + Send("AT+CIFSR"); CheckOnAnswer(); return ReturnInfo(); } @@ -118,7 +123,7 @@ bool WiFi::CreateCurrentHost(String name, String password, int port) { Open(); CheckOnAnswer(); - send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); + Send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); CheckOnAnswer(); UseTCP(port); } @@ -127,14 +132,14 @@ bool WiFi::CreateStaticHost(String name, String password, int port) { Open(); CheckOnAnswer(); - send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); + Send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); CheckOnAnswer(); UseTCP(port); } bool WiFi::Open() { - send("AT+CWMODE_CUR=2"); + Send("AT+CWMODE_CUR=2"); CheckOnAnswer(); opened = true; } @@ -142,22 +147,22 @@ bool WiFi::Open() String WiFi::NetsList() { Close(); - send("AT+CWLAP"); + Send("AT+CWLAP"); return ReturnInfo(); } bool WiFi::Close() { - send("AT+CWMODE_CUR=1"); + Send("AT+CWMODE_CUR=1"); CheckOnAnswer(); opened = false; } bool WiFi::UseTCP(int port) { - send("AT+CIPMUX=1"); + Send("AT+CIPMUX=1"); CheckOnAnswer(); - send("AT+CIPSERVER=1," + String(port)); + Send("AT+CIPSERVER=1," + String(port)); CheckOnAnswer(); } @@ -181,45 +186,99 @@ void WiFi::Send(String command) String WiFi::Scan() { delay(100); - return ConnectingDevice::read(); + String responce = ConnectingDevice::read(); + if (responce.indexOf(",CONNECT") == 1) + { + String ID = responce.substring(0, 1); + if ((atoi(ID.c_str()) - 1) == IDCount) + { + IDCount++; + Scan(); + } + else + { + FatalError(); + } + } + if (responce.indexOf("/r/n+IPD,") == 0) + { + String ID = responce.substring(7, 1); + String message = responce.substring(9, sizeof(responce) - 9); + String answer; + if (sizeof(message) < 11) + { + answer = message.substring(2, sizeof(message) - 4); + return answer; + } + if (11 <= sizeof(message) < 102) + { + answer = message.substring(3, sizeof(message) - 5); + return answer; + } + if (102 <= sizeof(message) < 1003) + { + answer = message.substring(4, sizeof(message) - 6); + return answer; + } + if (1003 <= sizeof(message) < 10004) + { + answer = message.substring(5, sizeof(message) - 7); + return answer; + } + } + else + { + return responce; + } } String WiFi::CheckStatus() { String response = ""; - if (isInited) - { - response += "Inited"; - } - if (!isInited) - { - response += "Not Inited"; - } if (ready) { - response += ", Ready"; + response += "Ready"; + if (opened) + { + response += ", Opened, " + String(IDCount+1) + " Connected"; + } + else + { + response += ", Closed"; + } + return response; } - if (!ready) + else { - response += ", Not Ready"; + response += "Fatal Error"; + return response; } - if (opened) +} + +String WiFi::Write(int ID, String message) +{ + if (-1 < ID <= IDCount) { - response += ", Opened"; + Send("AT+CIPSEND=" + String(ID) + sizeof(message)); + if (CheckOnAnswer()) + { + Send(message); + if (Scan() == ("busy s.../r/nRecv " + sizeof(message) + String(" bytes/r/nSEND OK"))) + { + return "Done"; + } + else + { + FatalError(); + } + } + else + { + FatalError(); + } } - if (!opened) + else { - response += ", Closed"; + return "Wrong ID"; } - return response; -} - -String WiFi::Write(String message) -{ - -} - -String WiFi::Read() -{ - } \ No newline at end of file diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index ef15ac2..edc06b9 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -100,7 +100,7 @@ class WiFi : public ConnectingDevice virtual void Send(String command); /** - * @brief Функция приёма ответа с модуля, добавляющая задержку перед получением ответа + * @brief Функция приёма ответа с модуля, добавляющая задержку перед получением ответа, а также редактирующая счётчик подключённых устройств */ virtual String Scan(); @@ -117,8 +117,9 @@ class WiFi : public ConnectingDevice /** * @brief Функция отправки данных пользователю + * @param ID адрес получателя и message строка с сообщением */ - virtual String Write(String message); + virtual String Write(int ID, String message); /** * @brief Функция приёма данных от пользователя @@ -137,6 +138,8 @@ class WiFi : public ConnectingDevice private: + int IDCount = -1; + /** * @brief Индикатор готовности модуля к работе */ @@ -146,4 +149,9 @@ class WiFi : public ConnectingDevice * @brief Индикатор состояния модуля клиент/хост */ bool opened = false; + + /** + * @brief Индикатор внутренней ошибки + */ + bool error = false; }; \ No newline at end of file From 4e161f0cc8b5bd8716f393ee1957f160a14b6302 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 27 Aug 2017 19:57:46 +0300 Subject: [PATCH 093/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20API=20v3=20=D0=BD=D0=B0=20arduino?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/CommandsEnum.h | 2 + code/Arduino/Constants.cpp | 2 + code/Arduino/Constants.h | 2 + .../peripheral/ConnectionController.cpp | 51 ++++++++++++++++--- .../Arduino/peripheral/ConnectionController.h | 4 ++ 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/code/Arduino/CommandsEnum.h b/code/Arduino/CommandsEnum.h index ded6a71..aaa019e 100644 --- a/code/Arduino/CommandsEnum.h +++ b/code/Arduino/CommandsEnum.h @@ -48,6 +48,7 @@ enum ServoCommands { enum CommunicationCommands { startCommunicationCommand = 1, //starting communication command stopCommunicationCommand = 2, //stopping communication command + refreshConnectionCommunicationCommand = 3, //refreshing connection timer communication command (since API v3) }; /** @@ -59,6 +60,7 @@ enum CommunicationCommands { enum StartCommands { startBasicAPI = 1, //default API v1 APIWithAnswer = 2, //API v2 + APIWithAutoDiconnect = 3, //API v3 }; #endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index 53bdfb8..d39258d 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -57,6 +57,8 @@ const uint8_t Constants::countDistanceSensors = 5; const uint8_t Constants::countLineSensors = 5; const uint16_t Constants::minimalLineBound = 270; +const uint32_t Constants::waitCommandTimeInMs = 2000; + Constants::Constants() { } diff --git a/code/Arduino/Constants.h b/code/Arduino/Constants.h index 47ea8b2..20dab05 100644 --- a/code/Arduino/Constants.h +++ b/code/Arduino/Constants.h @@ -52,6 +52,8 @@ class Constants static const uint8_t countLineSensors; static const uint16_t minimalLineBound; + static const uint32_t waitCommandTimeInMs; + Constants(); ~Constants(); }; diff --git a/code/Arduino/peripheral/ConnectionController.cpp b/code/Arduino/peripheral/ConnectionController.cpp index 5bbefe1..4a5310f 100644 --- a/code/Arduino/peripheral/ConnectionController.cpp +++ b/code/Arduino/peripheral/ConnectionController.cpp @@ -1,11 +1,13 @@ #include "../Constants.h" #include "../CommandsEnum.h" #include "../connectors/DebugSerial.h" +#include "../utils/Timer.h" #include "ConnectionController.h" const char ConnectionController::connectCommand[] = { communicationControllerID, startCommunicationCommand, 0 }; const char ConnectionController::disconnectCommand[] = { communicationControllerID, stopCommunicationCommand, 0 }; +const char ConnectionController::refreshCommand[] = { communicationControllerID, refreshConnectionCommunicationCommand, 0 }; ConnectionController::ConnectionController() : connectedAPIversion(startBasicAPI) { @@ -99,6 +101,32 @@ ConnectingDevice* ConnectionController::getDevice() const return device; } +bool ConnectionController::waitForCommandOnDevice(Timer* timer) +{ + //compatibility with API v1 & v2 + if (connectedAPIversion >= APIWithAutoDiconnect) + { + while (!device->isActive() && timer->getState() != timerState_finished) + { + delay(1); + } + + if (timer->getState() == timerState_finished) + { + return false; + } + } + else + { + while (!device->isActive()) + { + delay(1); + } + } + + return true; +} + String ConnectionController::getCommand() { if (!isConnected) @@ -107,11 +135,15 @@ String ConnectionController::getCommand() } String command; + Timer timer(Constants::waitCommandTimeInMs); + timer.startOrResume(); do { - while (!device->isActive()) + if (!waitForCommandOnDevice(&timer)) { - delay(1); + isConnected = false; + waitForConnection(); + continue; } command = device->read(); @@ -126,13 +158,20 @@ String ConnectionController::getCommand() DEBUG_PRINT("Command: "); DEBUG_PRINTLNHEX(command); - if (command != disconnectCommand) + if (command == disconnectCommand) + { + isConnected = false; + waitForConnection(); + continue; + } + + if (connectedAPIversion >= APIWithAutoDiconnect && command == refreshCommand) { - break; + timer.reset(); + continue; } - isConnected = false; - waitForConnection(); + break; } while (true); return command; } diff --git a/code/Arduino/peripheral/ConnectionController.h b/code/Arduino/peripheral/ConnectionController.h index 1762a14..797e961 100644 --- a/code/Arduino/peripheral/ConnectionController.h +++ b/code/Arduino/peripheral/ConnectionController.h @@ -3,6 +3,7 @@ #include "../connectors/Bluetooth.h" #include "../connectors/WiFi.h" #include "../CommandsEnum.h" +#include "../utils/Timer.h" class ConnectionController { @@ -13,12 +14,15 @@ class ConnectionController static const char connectCommand[]; static const char disconnectCommand[]; + static const char refreshCommand[]; static const StartCommands lowestAPI = startBasicAPI; static const StartCommands highestAPI = APIWithAnswer; bool isConnected = false; StartCommands connectedAPIversion; + bool waitForCommandOnDevice(Timer* timer); + public: ConnectionController(); ~ConnectionController(); From 50a74d4f81c9f07721691629010126a138478eb8 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Sun, 27 Aug 2017 21:48:58 +0300 Subject: [PATCH 094/336] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D1=8B=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D0=B2=D0=B0=D1=80=D0=BD=D0=B8=D0=BD=D0=B3?= =?UTF-8?q?=D0=B8.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B2=D1=8B=D1=87=D0=B8=D1=82=D1=8B=D0=B2=D0=B0=D0=B5?= =?UTF-8?q?=D0=BC=D1=8B=D1=85=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B8.=20=D0=98=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B0=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BA=D1=80=D0=B8=D1=82=D0=B8=D1=87=D0=B5=D1=81?= =?UTF-8?q?=D0=BA=D0=BE=D0=B9=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 223 ++++++++++++++++++++++--------- code/Arduino/connectors/WiFi.h | 17 +-- 2 files changed, 168 insertions(+), 72 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index c56e214..1936e4b 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -21,13 +21,14 @@ WiFi::~WiFi() bool WiFi::CheckOnReady() { StartingSend("AT"); - if (ready = (Scan() == "AT\r\nOK") == ReturningCommandsOff()) + if (ready != ((Scan() == "AT\r\nOK") == ReturningCommandsOff())) { - return ready; + return true; } else { Reset(); + return false; } } @@ -40,17 +41,11 @@ bool WiFi::ReturningCommandsOff() } else { - FatalError(); + Reset(); + return false; } } -void WiFi::FatalError() -{ - IDCount = -1; - ready = false; - opened = false; -} - bool WiFi::CheckOnAnswer() { if (Scan() = "\r\nOK") @@ -59,7 +54,8 @@ bool WiFi::CheckOnAnswer() } else { - FatalError(); + Reset(); + return false; } } @@ -69,13 +65,14 @@ bool WiFi::Reset() ready = false; opened = false; StartingSend("AT+RST"); - if (ready = (Scan() == "AT+RST\r\nOK") == ReturningCommandsOff()) + if (ready != ((Scan() == "AT+RST\r\nOK") == ReturningCommandsOff())) { - return ready; + return ready = true; } else { - FatalError(); + Reset(); + return false; } } @@ -83,14 +80,35 @@ bool WiFi::Reset(unsigned long speed) { if (Reset()) { - ChangeSpeed(speed); + if (ChangeSpeed(speed)) + { + return true; + } + else + { + Reset(); + return false; + } + } + else + { + Reset(); + return false; } } bool WiFi::ChangeSpeed(unsigned long speed) { Send("AT+CIOBAUD=" + String(speed)); - CheckOnAnswer(); + if (CheckOnAnswer()) + { + return true; + } + else + { + Reset(); + return false; + } } String WiFi::VersionCheck() @@ -108,62 +126,128 @@ String WiFi::ReturnInfo() } else { - FatalError(); + Reset(); + return ""; } } String WiFi::CheckIPandMAC() { Send("AT+CIFSR"); - CheckOnAnswer(); - return ReturnInfo(); + if (CheckOnAnswer()) + { + return ReturnInfo(); + } + else + { + Reset(); + return ""; + } } bool WiFi::CreateCurrentHost(String name, String password, int port) { - Open(); - CheckOnAnswer(); - Send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); - CheckOnAnswer(); - UseTCP(port); -} - -bool WiFi::CreateStaticHost(String name, String password, int port) -{ - Open(); - CheckOnAnswer(); - Send("AT+CWSAP_DEF=" + name + "," + password + ",5,3"); - CheckOnAnswer(); - UseTCP(port); + if (Open()) + { + if (CheckOnAnswer()) + { + Send("AT+CWSAP_CUR=" + name + "," + password + ",5,3"); + if (CheckOnAnswer()) + { + if (UseTCP(port)) + { + return true; + } + else + { + Reset(); + return false; + } + } + else + { + Reset(); + return false; + } + } + else + { + Reset(); + return false; + } + } + else + { + Reset(); + return false; + } } bool WiFi::Open() { Send("AT+CWMODE_CUR=2"); - CheckOnAnswer(); - opened = true; + if (CheckOnAnswer()) + { + opened = true; + return true; + } + else + { + Reset(); + return false; + } } String WiFi::NetsList() { - Close(); - Send("AT+CWLAP"); - return ReturnInfo(); + if (Close()) + { + Send("AT+CWLAP"); + return ReturnInfo(); + } + else + { + Reset(); + return ""; + } } bool WiFi::Close() { Send("AT+CWMODE_CUR=1"); - CheckOnAnswer(); - opened = false; + if (CheckOnAnswer()) + { + opened = false; + return true; + } + else + { + Reset(); + return false; + } } bool WiFi::UseTCP(int port) { Send("AT+CIPMUX=1"); - CheckOnAnswer(); - Send("AT+CIPSERVER=1," + String(port)); - CheckOnAnswer(); + if (CheckOnAnswer()) + { + Send("AT+CIPSERVER=1," + String(port)); + if (CheckOnAnswer()) + { + return true; + } + else + { + Reset(); + return false; + } + } + else + { + Reset(); + return false; + } } void WiFi::StartingSend(String command) @@ -179,25 +263,41 @@ void WiFi::Send(String command) } else { - FatalError(); + Reset(); } } +void WiFi::send(String message) +{ + Write(0, message); +} + +String WiFi::read() +{ + return Scan(); +} + +String WiFi::Read() +{ + return device->readStringUntil('\r'); +} + String WiFi::Scan() { delay(100); - String responce = ConnectingDevice::read(); + String responce = Read(); if (responce.indexOf(",CONNECT") == 1) { String ID = responce.substring(0, 1); if ((atoi(ID.c_str()) - 1) == IDCount) { IDCount++; - Scan(); + return Scan(); } else { - FatalError(); + Reset(); + return ""; } } if (responce.indexOf("/r/n+IPD,") == 0) @@ -207,22 +307,22 @@ String WiFi::Scan() String answer; if (sizeof(message) < 11) { - answer = message.substring(2, sizeof(message) - 4); + answer = message.substring(2, sizeof(message) - 2); return answer; } - if (11 <= sizeof(message) < 102) + if (sizeof(message) < 102) { - answer = message.substring(3, sizeof(message) - 5); + answer = message.substring(3, sizeof(message) - 3); return answer; } - if (102 <= sizeof(message) < 1003) + if (sizeof(message) < 1003) { - answer = message.substring(4, sizeof(message) - 6); + answer = message.substring(4, sizeof(message) - 4); return answer; } - if (1003 <= sizeof(message) < 10004) + if (sizeof(message) < 10004) { - answer = message.substring(5, sizeof(message) - 7); + answer = message.substring(5, sizeof(message) - 5); return answer; } } @@ -255,9 +355,9 @@ String WiFi::CheckStatus() } } -String WiFi::Write(int ID, String message) +bool WiFi::Write(int ID, String message) { - if (-1 < ID <= IDCount) + if (ID > -1 && ID <= IDCount) { Send("AT+CIPSEND=" + String(ID) + sizeof(message)); if (CheckOnAnswer()) @@ -265,20 +365,23 @@ String WiFi::Write(int ID, String message) Send(message); if (Scan() == ("busy s.../r/nRecv " + sizeof(message) + String(" bytes/r/nSEND OK"))) { - return "Done"; + return true; } else { - FatalError(); + Reset(); + return false; } } else { - FatalError(); + Reset(); + return false; } } else { - return "Wrong ID"; + Reset(); + return false; } } \ No newline at end of file diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index edc06b9..a127056 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -83,12 +83,6 @@ class WiFi : public ConnectingDevice */ virtual bool CreateCurrentHost(String name, String password, int port); - /** - * @brief Устанавливает параметры хоста с записью в кэш - * @param name имя точки доступа, password пароль и port номер порта для вызова функции UseTCP - */ - virtual bool CreateStaticHost(String name, String password, int port); - /** * @brief Функция отправки, добавляющая "\r\n" ко всем командам без проверки статуса модуля */ @@ -110,16 +104,11 @@ class WiFi : public ConnectingDevice */ virtual String ReturnInfo(); - /** - * @brief Функция выхода при критической ошибке - */ - virtual void FatalError(); - /** * @brief Функция отправки данных пользователю * @param ID адрес получателя и message строка с сообщением */ - virtual String Write(int ID, String message); + virtual bool Write(int ID, String message); /** * @brief Функция приёма данных от пользователя @@ -136,6 +125,10 @@ class WiFi : public ConnectingDevice */ bool isInited = false; + String read() override; + + void send(String message) override; + private: int IDCount = -1; From 95b32e39c95ad69cfb78f0b68c9aa4a3f3f2e308 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Sun, 27 Aug 2017 23:45:43 +0300 Subject: [PATCH 095/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B8?= =?UTF-8?q?=D1=82=D1=8C,=20=D0=B8=20=D0=B4=D0=B0=D1=82=D1=87=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BB=D0=B8=D0=BD=D0=BD=D0=B8,=20=D0=B8=20=D0=B4?= =?UTF-8?q?=D0=B0=D1=82=D1=87=D0=B8=D0=BA=D0=B8=20=D0=B4=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D1=86=D0=B8=D0=B8=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D0=BE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/SensorsViewer.cpp | 49 ++++++++++++++++++++++-------- code/c++/cxx-app/SensorsViewer.h | 5 +-- code/c++/cxx-app/main.cpp | 5 ++- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/code/c++/cxx-app/SensorsViewer.cpp b/code/c++/cxx-app/SensorsViewer.cpp index 354edc6..202a9ad 100644 --- a/code/c++/cxx-app/SensorsViewer.cpp +++ b/code/c++/cxx-app/SensorsViewer.cpp @@ -1,28 +1,53 @@ #include "SensorsViewer.h" void SensorsViewer::setData(const std::vector& d, SensorType t) { - data = d; - type = t; + if (t == LINE_SENSORS) { + lineSensors = d; + } + else { + distanceSensors = d; + } } void SensorsViewer::show() { + if (system("clear")) system("cls"); + if (!distanceSensors.empty()) { + if (system("clear")) system("cls"); + std::cout << "Distance sensors:" << std::endl; + if (distanceSensors.size() >= 1) std::cout << " " << std::setw(4) << distanceSensors[0] << std::endl; + if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); + if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; + if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); + if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; + } + if (!lineSensors.empty()) { + std::cout << "Line sensors:" << std::endl; + std::cout << "|"; + for (int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); + } + std::cout << "|"; + } + } + void SensorsViewer::show(SensorType type) { if (type == LINE_SENSORS) { - if (!data.empty()) { + if (!lineSensors.empty()) { std::cout << "\r" << "|"; - for (int i = 0; i < data.size(); i++) { - std::cout << (data[i] ? "@@@" : " "); + for (int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); } std::cout << "|"; } } else { - if (!data.empty()) { + if (!distanceSensors.empty()) { if (system("clear")) system("cls"); - if (data.size() >= 1) std::cout << " " << std::setw(4) << data[0] << std::endl; - if (data.size() >= 2) std::cout << " " << std::setw(4) << data[1] << (data.size() == 2 ? "\n" : ""); - if (data.size() >= 3) std::cout << " " << std::setw(4) << data[2] << std::endl; - if (data.size() >= 4) std::cout << " " << std::setw(4) << data[3] << (data.size() == 4 ? "\n" : ""); - if (data.size() >= 5) std::cout << " " << std::setw(4) << data[4] << std::endl; + std::cout << "Distance sensors:" << std::endl; + if (distanceSensors.size() >= 1) std::cout << " " << std::setw(4) << distanceSensors[0] << std::endl; + if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); + if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; + if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); + if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; } } - } \ No newline at end of file +} \ No newline at end of file diff --git a/code/c++/cxx-app/SensorsViewer.h b/code/c++/cxx-app/SensorsViewer.h index 979afdb..365b345 100644 --- a/code/c++/cxx-app/SensorsViewer.h +++ b/code/c++/cxx-app/SensorsViewer.h @@ -9,10 +9,11 @@ enum SensorType { }; class SensorsViewer { - std::vector data; - SensorType type; + std::vector lineSensors; + std::vector distanceSensors; public: void setData(const std::vector& d, SensorType t); void show(); + void show(SensorType type); }; \ No newline at end of file diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 5346f97..c09cf6f 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -13,6 +13,7 @@ int main(int argc, char* argv[]) { + std::string rx = "COM13", tx = "COM13"; uint32_t baudrate = 9600U; @@ -27,7 +28,7 @@ int main(int argc, char* argv[]) std::cin >> baudrate; */ std::cout << "rx = " << rx << " tx = " << tx << " baudrate = " << baudrate << " ip = " << ip << " port = " << port << std::endl; - + try { CommunicationInfoStruct info; @@ -38,9 +39,11 @@ int main(int argc, char* argv[]) TrackPlatform_Manager trackPlatform(bluetooth, info); #else + info.TCPIPInfo.ip = ip; info.TCPIPInfo.port = port; TrackPlatform_Manager trackPlatform(WiFi, info); + #endif bool isExit = false; From 6db1d2af37bf18b01f0d8b1097abbe5516a429d3 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 30 Aug 2017 12:49:49 +0300 Subject: [PATCH 096/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=B4=D1=82=D0=B2=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/CommandsEnum.h | 1 + code/c++/cxx-api/TCPIP_Connector.cpp | 3 +-- code/c++/cxx-api/TrackPlatform_BasicConnector.cpp | 2 +- code/c++/cxx-api/TrackPlatform_BasicManagement.cpp | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/code/c++/cxx-api/CommandsEnum.h b/code/c++/cxx-api/CommandsEnum.h index f781da2..94578ea 100644 --- a/code/c++/cxx-api/CommandsEnum.h +++ b/code/c++/cxx-api/CommandsEnum.h @@ -56,6 +56,7 @@ enum CommunicationCommands { */ enum StartCommands { startBasicAPI = 1, //default API v1 + APIWithAnswer = 2 //API v2 }; #endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/c++/cxx-api/TCPIP_Connector.cpp b/code/c++/cxx-api/TCPIP_Connector.cpp index 056f354..f868317 100644 --- a/code/c++/cxx-api/TCPIP_Connector.cpp +++ b/code/c++/cxx-api/TCPIP_Connector.cpp @@ -218,5 +218,4 @@ TCPIP_Connector::~TCPIP_Connector() #ifdef _WIN32 WSACleanup(); #endif -} - +} \ No newline at end of file diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index 7100d14..0b8673e 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -14,7 +14,7 @@ const std::string TrackPlatform_BasicConnector::connectedAnswer = "OK"; void TrackPlatform_BasicConnector::sendStartCommand() { - std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(startBasicAPI); + std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(APIWithAnswer); isConnectedToArduino = true; for (auto i = 0; i < timesToAutoreconnect; ++i) { diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index bc0c54f..97157cf 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -4,6 +4,7 @@ void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(movementControllerID) + additionalInfo); + auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } @@ -11,6 +12,7 @@ void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInf { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(sensorsControllerID) + additionalInfo); + auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } @@ -18,6 +20,7 @@ void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(servoControllerID) + additionalInfo); + auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } From 7f5335e11698bfb7c9b718f96e5b8826badb2d37 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 30 Aug 2017 13:20:48 +0300 Subject: [PATCH 097/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20api?= =?UTF-8?q?=20v3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/CommandsEnum.h | 3 ++- code/c++/cxx-api/TrackPlatform_BasicConnector.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-api/CommandsEnum.h b/code/c++/cxx-api/CommandsEnum.h index 94578ea..5a1f9cf 100644 --- a/code/c++/cxx-api/CommandsEnum.h +++ b/code/c++/cxx-api/CommandsEnum.h @@ -56,7 +56,8 @@ enum CommunicationCommands { */ enum StartCommands { startBasicAPI = 1, //default API v1 - APIWithAnswer = 2 //API v2 + APIWithAnswer = 2, //API v2 + APIWithAutoDiconnect = 3 //API v3 }; #endif /* _COMMANDS_ENUM_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index 0b8673e..4a2f3a2 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -14,7 +14,7 @@ const std::string TrackPlatform_BasicConnector::connectedAnswer = "OK"; void TrackPlatform_BasicConnector::sendStartCommand() { - std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(APIWithAnswer); + std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(APIWithAutoDiconnect); isConnectedToArduino = true; for (auto i = 0; i < timesToAutoreconnect; ++i) { From 9dec52527d968a523f97ff13d02c50e45d1645a9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 30 Aug 2017 20:23:11 +0300 Subject: [PATCH 098/336] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BF=D0=BB=D0=B0=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BF=D1=83=D1=81=D0=BA=D0=B0=20=D0=BC=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=20(=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=D0=B5=D0=BD=D0=BE=20=D0=BD=D0=B0=20=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D1=8B=D0=B5=20=D0=BF=D0=B8=D0=BD?= =?UTF-8?q?=D1=8B,=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D1=8E=D1=89=D0=B8=D0=B5=20=D0=A8=D0=98=D0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/Constants.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Arduino/Constants.cpp b/code/Arduino/Constants.cpp index d39258d..a286d7f 100644 --- a/code/Arduino/Constants.cpp +++ b/code/Arduino/Constants.cpp @@ -21,12 +21,12 @@ const uint8_t Constants::dbg_uart_TX = 18; const uint32_t Constants::dbg_uart_speed = 9600; /* Movement controller (L298N) */ -const uint8_t Constants::left_engine_enable = A8; +const uint8_t Constants::left_engine_enable = 10; const uint8_t Constants::left_engine_straight_pin = 30; const uint8_t Constants::left_engine_reverse_pin = 31; const uint8_t Constants::right_engine_straight_pin = 32; const uint8_t Constants::right_engine_reverse_pin = 33; -const uint8_t Constants::right_engine_enable = A9; +const uint8_t Constants::right_engine_enable = 11; /* Distanse controller */ const uint8_t Constants::distance_sensor_read_pin = A0; From b3fecbc188b7ae92d1fa1c2ae0dad60f67d3955a Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 30 Aug 2017 20:43:23 +0300 Subject: [PATCH 099/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BC=D0=B0=D0=BA=D1=81?= =?UTF-8?q?=D0=B8=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D1=81=D1=82=D0=B8=20=D0=BF=D0=BE=D0=B2=D0=BE?= =?UTF-8?q?=D1=80=D0=BE=D1=82=D0=B0=20=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B5.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BA=D0=B0=D0=BB=D0=B8=D0=B1=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9?= =?UTF-8?q?=20=D1=81=D0=BA=D0=BE=D1=80=D0=BE=D1=81=D1=82=D0=B5=D0=B9=20?= =?UTF-8?q?=D0=B3=D1=83=D1=81=D0=B5=D0=BD=D0=B8=D1=86=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=B2=20API.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadManager.cpp | 18 +++++++++++++++--- code/c++/cxx-gamepad-app/GamepadManager.h | 9 ++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp index 5f262f8..981f73f 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.cpp +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -5,7 +5,8 @@ #include "GamepadManager.h" -const double GamepadManager::forwardMultiplier = 0.6; +const double GamepadManager::forwardMaxSpeed = 0.6; +const double GamepadManager::rotateMaxSpeed = 0.6; GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), runnedThread(nullptr) { @@ -77,12 +78,23 @@ bool GamepadManager::convertAndSendMovement(double xValue, double yValue) return false; } - if (!trackPlatform->setTrackForwardSpeed(left_track, yValue * forwardMultiplier - xValue * (1 - forwardMultiplier))) + double leftTrackSpeed = yValue * forwardMaxSpeed - xValue * rotateMaxSpeed; + double rightTrackSpeed = yValue * forwardMaxSpeed + xValue * rotateMaxSpeed; + + //calibrating values + auto catibrator = [](double current, double min, double max) -> double + { + return ((current > max) ? max : ((current < min) ? min : current)); + }; + leftTrackSpeed = catibrator(leftTrackSpeed, -1, 1); + rightTrackSpeed = catibrator(rightTrackSpeed, -1, 1); + + if (!trackPlatform->setTrackForwardSpeed(left_track, leftTrackSpeed)) { return false; } - if (!trackPlatform->setTrackForwardSpeed(right_track, yValue * forwardMultiplier + xValue * (1 - forwardMultiplier))) + if (!trackPlatform->setTrackForwardSpeed(right_track, rightTrackSpeed)) { return false; } diff --git a/code/c++/cxx-gamepad-app/GamepadManager.h b/code/c++/cxx-gamepad-app/GamepadManager.h index 39ca564..b31a246 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.h +++ b/code/c++/cxx-gamepad-app/GamepadManager.h @@ -20,7 +20,14 @@ class GamepadManager GamepadConfig config; - static const double forwardMultiplier; + /** + * @brief Max speed to move forward. Sould be in interval [0; 1] + */ + static const double forwardMaxSpeed; + /** + * @brief Max speed to rotate. Sould be in interval [0; 1] + */ + static const double rotateMaxSpeed; public: GamepadManager(TrackPlatform_Manager* trackPlatform); From 5f6abc818b0c65a5600a133a972e94b0492ea43f Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 31 Aug 2017 10:43:39 +0300 Subject: [PATCH 100/336] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B0=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B0=20=D0=B8=D0=BD=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D1=81=20=D0=B4=D0=B0?= =?UTF-8?q?=D1=82=D1=87=D0=B8=D0=BA=D0=BE=D0=B2=20=D1=80=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8F=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=8D=D0=BA=D1=80=D0=B0=D0=BD.=20=D0=A2=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C=20=D0=BE=D0=BD=20=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=81=D0=B8=D1=82=20=D0=BE=D1=82=20=D0=BA=D0=BE=D0=BB?= =?UTF-8?q?=D0=B8=D1=87=D0=B5=D1=81=D1=82=D0=B2=D0=B0=20=D0=B4=D0=B0=D1=82?= =?UTF-8?q?=D1=87=D0=B8=D0=BA=D0=BE=D0=B2=20=D0=B8=20=D0=BC=D0=BE=D0=B6?= =?UTF-8?q?=D0=B5=D1=82=20=D0=B1=D1=8B=D1=82=D1=8C=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD.=20=D0=A2=D0=B0=D0=BA=D0=B6?= =?UTF-8?q?=D0=B5=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B2=D1=81?= =?UTF-8?q?=D1=8F=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D1=81=D1=8F?= =?UTF-8?q?=20=D1=81=D0=BB=D0=B5=D0=B2=D0=B0=20=D0=BD=D0=B0=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=83=D0=BA=D1=80=D1=83?= =?UTF-8?q?=D0=B3=D0=BE=D0=BC=20(=D0=BF=D0=BE=20=D1=87=D0=B0=D1=81=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=B5=D0=BB=D0=BA=D0=B5?= =?UTF-8?q?),=20=D0=B0=20=D0=BD=D0=B5=20=D0=B5=D0=BB=D0=BE=D1=87=D0=BA?= =?UTF-8?q?=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/SensorsViewer.cpp | 100 ++++++++++++++++++----------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/code/c++/cxx-app/SensorsViewer.cpp b/code/c++/cxx-app/SensorsViewer.cpp index 202a9ad..51bd217 100644 --- a/code/c++/cxx-app/SensorsViewer.cpp +++ b/code/c++/cxx-app/SensorsViewer.cpp @@ -1,16 +1,69 @@ #include "SensorsViewer.h" - void SensorsViewer::setData(const std::vector& d, SensorType t) { - if (t == LINE_SENSORS) { - lineSensors = d; +void SensorsViewer::setData(const std::vector& d, SensorType t) { + if (t == LINE_SENSORS) { + lineSensors = d; + } + else { + distanceSensors = d; + } +} + +void SensorsViewer::show() { + if (system("clear")) system("cls"); + if (!distanceSensors.empty()) { + //configuration + const short prefixSymbolNum = 1; + const short betweenSymbolNum = 1; + const short oneNumMinSize = 4; + const char delimiter = ' '; + std::ostream& os = std::cout; + + const short isParityOn = distanceSensors.size() % 2; + const short stringNums = distanceSensors.size() / 2; + os << "Distance sensors:" << std::endl; + auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& + { + while(num > 0) + { + s << c; + num--; + } + return s; + }; + if (isParityOn) + { + printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << + distanceSensors[stringNums] << std::endl; + } + for (short i = 0; i < stringNums; ++i) + { + printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << + std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; + printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << + distanceSensors[stringNums + i + isParityOn - 1] << std::endl; + } + } + if (!lineSensors.empty()) { + std::cout << "Line sensors:" << std::endl; + std::cout << "|"; + for (unsigned int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); } - else { - distanceSensors = d; + std::cout << "|" << std::endl; + } +} +void SensorsViewer::show(SensorType type) { + if (type == LINE_SENSORS) { + if (!lineSensors.empty()) { + std::cout << "\r" << "|"; + for (unsigned int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); + } + std::cout << "|"; } } - - void SensorsViewer::show() { - if (system("clear")) system("cls"); + else { if (!distanceSensors.empty()) { if (system("clear")) system("cls"); std::cout << "Distance sensors:" << std::endl; @@ -18,36 +71,7 @@ if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); - if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; - } - if (!lineSensors.empty()) { - std::cout << "Line sensors:" << std::endl; - std::cout << "|"; - for (int i = 0; i < lineSensors.size(); i++) { - std::cout << (lineSensors[i] ? "@@@" : " "); - } - std::cout << "|"; + if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; } } - void SensorsViewer::show(SensorType type) { - if (type == LINE_SENSORS) { - if (!lineSensors.empty()) { - std::cout << "\r" << "|"; - for (int i = 0; i < lineSensors.size(); i++) { - std::cout << (lineSensors[i] ? "@@@" : " "); - } - std::cout << "|"; - } - } - else { - if (!distanceSensors.empty()) { - if (system("clear")) system("cls"); - std::cout << "Distance sensors:" << std::endl; - if (distanceSensors.size() >= 1) std::cout << " " << std::setw(4) << distanceSensors[0] << std::endl; - if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); - if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; - if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); - if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; - } - } } \ No newline at end of file From a5d1e7023e93e868c3bcd713c2d46ea71f77e0b6 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 31 Aug 2017 10:44:11 +0300 Subject: [PATCH 101/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BD=D0=B0=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/code/c++/cxx-app/makefile b/code/c++/cxx-app/makefile index 456aefe..63ca49d 100644 --- a/code/c++/cxx-app/makefile +++ b/code/c++/cxx-app/makefile @@ -74,6 +74,7 @@ ARFLAGS = SOURCES = # Other code (non grouped) SOURCES += $(OTHER_SOURCE_PATH)/main.cpp +SOURCES += $(OTHER_SOURCE_PATH)/SensorsViewer.cpp #Include file path INCLUDES = From e95dcd74057dd0d886f760de638674715a82392f Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 31 Aug 2017 11:43:21 +0300 Subject: [PATCH 102/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D1=81=D0=B5=D0=B2=D0=B4=D0=BE=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D1=84=D0=B8=D0=BA=D0=B8=20=D0=B4=D0=BB=D1=8F=20gamepad-?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/GamepadManager.cpp | 11 ++- code/c++/cxx-gamepad-app/GamepadManager.h | 7 ++ code/c++/cxx-gamepad-app/SensorsViewer.cpp | 77 +++++++++++++++++++ code/c++/cxx-gamepad-app/SensorsViewer.h | 19 +++++ .../cxx-gamepad-app/cxx-gamepad-app.vcxproj | 2 + .../cxx-gamepad-app.vcxproj.filters | 6 ++ .../c++/cxx-gamepad-app/gamepad_callbacks.cpp | 6 +- 7 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.cpp create mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.h diff --git a/code/c++/cxx-gamepad-app/GamepadManager.cpp b/code/c++/cxx-gamepad-app/GamepadManager.cpp index 5f262f8..43957f8 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.cpp +++ b/code/c++/cxx-gamepad-app/GamepadManager.cpp @@ -7,7 +7,7 @@ const double GamepadManager::forwardMultiplier = 0.6; -GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), runnedThread(nullptr) +GamepadManager::GamepadManager(TrackPlatform_Manager* trackPlatform) : trackPlatform(trackPlatform), sensorsViewer(new SensorsViewer), runnedThread(nullptr) { Gamepad_buttonDownFunc(onButtonDown, (void *)this); Gamepad_buttonUpFunc(onButtonUp, (void *)this); @@ -24,6 +24,10 @@ GamepadManager::~GamepadManager() delete runnedThread; } Gamepad_shutdown(); + if (sensorsViewer) + { + delete sensorsViewer; + } } void GamepadManager::run() @@ -70,6 +74,11 @@ TrackPlatform_Manager* GamepadManager::getTrackPlatformManager() const return trackPlatform; } +SensorsViewer* GamepadManager::getSensorsViewer() const +{ + return sensorsViewer; +} + bool GamepadManager::convertAndSendMovement(double xValue, double yValue) { if (!trackPlatform || (xValue > 1) || (xValue < -1) || (yValue > 1) || (yValue < -1)) diff --git a/code/c++/cxx-gamepad-app/GamepadManager.h b/code/c++/cxx-gamepad-app/GamepadManager.h index 39ca564..cbce23d 100644 --- a/code/c++/cxx-gamepad-app/GamepadManager.h +++ b/code/c++/cxx-gamepad-app/GamepadManager.h @@ -5,10 +5,12 @@ #include #include "TrackPlatform_Manager.h" #include "GamepadConfig.h" +#include "SensorsViewer.h" class GamepadManager { TrackPlatform_Manager* trackPlatform = nullptr; + SensorsViewer* sensorsViewer = nullptr; /** * @brief mutex is locked when handler thread is running, else not locked */ @@ -47,6 +49,11 @@ class GamepadManager * @return Current trackPlatform manager */ TrackPlatform_Manager* getTrackPlatformManager() const; + /** + * @brief Get current SensorsViewer + * @return Current SensorsViewer + */ + SensorsViewer* getSensorsViewer() const; /** * @brief Convert gamepad x and y values to movement speed of tracks and send it to device * @param xValue X axis value (must be in interval [-1; 1]) diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.cpp b/code/c++/cxx-gamepad-app/SensorsViewer.cpp new file mode 100644 index 0000000..51bd217 --- /dev/null +++ b/code/c++/cxx-gamepad-app/SensorsViewer.cpp @@ -0,0 +1,77 @@ +#include "SensorsViewer.h" + +void SensorsViewer::setData(const std::vector& d, SensorType t) { + if (t == LINE_SENSORS) { + lineSensors = d; + } + else { + distanceSensors = d; + } +} + +void SensorsViewer::show() { + if (system("clear")) system("cls"); + if (!distanceSensors.empty()) { + //configuration + const short prefixSymbolNum = 1; + const short betweenSymbolNum = 1; + const short oneNumMinSize = 4; + const char delimiter = ' '; + std::ostream& os = std::cout; + + const short isParityOn = distanceSensors.size() % 2; + const short stringNums = distanceSensors.size() / 2; + os << "Distance sensors:" << std::endl; + auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& + { + while(num > 0) + { + s << c; + num--; + } + return s; + }; + if (isParityOn) + { + printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << + distanceSensors[stringNums] << std::endl; + } + for (short i = 0; i < stringNums; ++i) + { + printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << + std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; + printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << + distanceSensors[stringNums + i + isParityOn - 1] << std::endl; + } + } + if (!lineSensors.empty()) { + std::cout << "Line sensors:" << std::endl; + std::cout << "|"; + for (unsigned int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); + } + std::cout << "|" << std::endl; + } +} +void SensorsViewer::show(SensorType type) { + if (type == LINE_SENSORS) { + if (!lineSensors.empty()) { + std::cout << "\r" << "|"; + for (unsigned int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); + } + std::cout << "|"; + } + } + else { + if (!distanceSensors.empty()) { + if (system("clear")) system("cls"); + std::cout << "Distance sensors:" << std::endl; + if (distanceSensors.size() >= 1) std::cout << " " << std::setw(4) << distanceSensors[0] << std::endl; + if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); + if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; + if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); + if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; + } + } +} \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.h b/code/c++/cxx-gamepad-app/SensorsViewer.h new file mode 100644 index 0000000..365b345 --- /dev/null +++ b/code/c++/cxx-gamepad-app/SensorsViewer.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include +#include + +enum SensorType { + LINE_SENSORS, DISTANCE_SENSORS +}; + +class SensorsViewer { + std::vector lineSensors; + std::vector distanceSensors; + +public: + void setData(const std::vector& d, SensorType t); + void show(); + void show(SensorType type); +}; \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj index 59b5900..e36df31 100644 --- a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj @@ -162,11 +162,13 @@ + + diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters index be33393..9fc07e4 100644 --- a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + @@ -38,5 +41,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp index ca877b4..5fe36ec 100644 --- a/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp +++ b/code/c++/cxx-gamepad-app/gamepad_callbacks.cpp @@ -12,12 +12,14 @@ void onButtonDown(Gamepad_device* device, unsigned buttonID, double timestamp, v } case GamepadCommands::lineSensorRefresh: { auto values = manager->getTrackPlatformManager()->sensorLineGetAllValues(); - //TODO: show on screen + manager->getSensorsViewer()->setData(values, LINE_SENSORS); + manager->getSensorsViewer()->show(); break; } case GamepadCommands::distanceSensorRefresh: { auto values = manager->getTrackPlatformManager()->sensorDistanceGetAllValues(); - //TODO: show on screen + manager->getSensorsViewer()->setData(values, DISTANCE_SENSORS); + manager->getSensorsViewer()->show(); break; } default: break; From 1eb3b704f3a9d3280a859f94f04a3b6a027cf8ba Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 31 Aug 2017 12:14:23 +0300 Subject: [PATCH 103/336] =?UTF-8?q?=D0=A1=D0=BA=D0=BE=D1=80=D1=80=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20SensorsViewer:=20=D0=B5=D1=81?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D1=8C?= =?UTF-8?q?=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BE=D0=B4=D0=B8=D0=BD=D0=BE=D1=87=D0=BA=D0=B5?= =?UTF-8?q?=20(=D0=BD=D0=B0=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80,=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BB=D0=B8=D0=BD=D0=B8=D0=B8?= =?UTF-8?q?),=20=D1=82=D0=BE=20=D0=BE=D0=BD=D0=B0=20=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B6=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=D0=B6=D0=B5,=20=D0=BA=D0=B0=D0=BA=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B5=20=D0=B2=D1=81?= =?UTF-8?q?=D0=B5=D0=B3=D0=BE=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-app/SensorsViewer.cpp | 111 ++++++++++----------- code/c++/cxx-app/SensorsViewer.h | 3 + code/c++/cxx-gamepad-app/SensorsViewer.cpp | 111 ++++++++++----------- code/c++/cxx-gamepad-app/SensorsViewer.h | 3 + 4 files changed, 114 insertions(+), 114 deletions(-) diff --git a/code/c++/cxx-app/SensorsViewer.cpp b/code/c++/cxx-app/SensorsViewer.cpp index 51bd217..4e9ec81 100644 --- a/code/c++/cxx-app/SensorsViewer.cpp +++ b/code/c++/cxx-app/SensorsViewer.cpp @@ -1,49 +1,44 @@ #include "SensorsViewer.h" -void SensorsViewer::setData(const std::vector& d, SensorType t) { - if (t == LINE_SENSORS) { - lineSensors = d; - } - else { - distanceSensors = d; - } -} - -void SensorsViewer::show() { - if (system("clear")) system("cls"); +void SensorsViewer::showDistanceInfo() +{ if (!distanceSensors.empty()) { - //configuration - const short prefixSymbolNum = 1; - const short betweenSymbolNum = 1; - const short oneNumMinSize = 4; - const char delimiter = ' '; - std::ostream& os = std::cout; + //configuration + const short prefixSymbolNum = 1; + const short betweenSymbolNum = 1; + const short oneNumMinSize = 4; + const char delimiter = ' '; + std::ostream& os = std::cout; - const short isParityOn = distanceSensors.size() % 2; - const short stringNums = distanceSensors.size() / 2; - os << "Distance sensors:" << std::endl; - auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& - { - while(num > 0) - { - s << c; - num--; - } - return s; - }; - if (isParityOn) - { - printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << - distanceSensors[stringNums] << std::endl; - } - for (short i = 0; i < stringNums; ++i) - { - printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << - std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; - printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << - distanceSensors[stringNums + i + isParityOn - 1] << std::endl; - } + const short isParityOn = distanceSensors.size() % 2; + const short stringNums = distanceSensors.size() / 2; + os << "Distance sensors:" << std::endl; + const auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& + { + while (num > 0) + { + s << c; + num--; + } + return s; + }; + if (isParityOn) + { + printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << + distanceSensors[stringNums] << std::endl; + } + for (short i = 0; i < stringNums; ++i) + { + printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << + std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; + printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << + distanceSensors[stringNums + i + isParityOn - 1] << std::endl; + } } +} + +void SensorsViewer::showLineInfo() +{ if (!lineSensors.empty()) { std::cout << "Line sensors:" << std::endl; std::cout << "|"; @@ -53,25 +48,27 @@ void SensorsViewer::show() { std::cout << "|" << std::endl; } } + +void SensorsViewer::setData(const std::vector& d, SensorType t) { + if (t == LINE_SENSORS) { + lineSensors = d; + } + else { + distanceSensors = d; + } +} + +void SensorsViewer::show() { + if (system("clear")) system("cls"); + showDistanceInfo(); + showLineInfo(); +} void SensorsViewer::show(SensorType type) { if (type == LINE_SENSORS) { - if (!lineSensors.empty()) { - std::cout << "\r" << "|"; - for (unsigned int i = 0; i < lineSensors.size(); i++) { - std::cout << (lineSensors[i] ? "@@@" : " "); - } - std::cout << "|"; - } + showLineInfo(); } else { - if (!distanceSensors.empty()) { - if (system("clear")) system("cls"); - std::cout << "Distance sensors:" << std::endl; - if (distanceSensors.size() >= 1) std::cout << " " << std::setw(4) << distanceSensors[0] << std::endl; - if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); - if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; - if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); - if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; - } + if (system("clear")) system("cls"); + showDistanceInfo(); } } \ No newline at end of file diff --git a/code/c++/cxx-app/SensorsViewer.h b/code/c++/cxx-app/SensorsViewer.h index 365b345..c343f27 100644 --- a/code/c++/cxx-app/SensorsViewer.h +++ b/code/c++/cxx-app/SensorsViewer.h @@ -12,6 +12,9 @@ class SensorsViewer { std::vector lineSensors; std::vector distanceSensors; + void showDistanceInfo(); + void showLineInfo(); + public: void setData(const std::vector& d, SensorType t); void show(); diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.cpp b/code/c++/cxx-gamepad-app/SensorsViewer.cpp index 51bd217..4e9ec81 100644 --- a/code/c++/cxx-gamepad-app/SensorsViewer.cpp +++ b/code/c++/cxx-gamepad-app/SensorsViewer.cpp @@ -1,49 +1,44 @@ #include "SensorsViewer.h" -void SensorsViewer::setData(const std::vector& d, SensorType t) { - if (t == LINE_SENSORS) { - lineSensors = d; - } - else { - distanceSensors = d; - } -} - -void SensorsViewer::show() { - if (system("clear")) system("cls"); +void SensorsViewer::showDistanceInfo() +{ if (!distanceSensors.empty()) { - //configuration - const short prefixSymbolNum = 1; - const short betweenSymbolNum = 1; - const short oneNumMinSize = 4; - const char delimiter = ' '; - std::ostream& os = std::cout; + //configuration + const short prefixSymbolNum = 1; + const short betweenSymbolNum = 1; + const short oneNumMinSize = 4; + const char delimiter = ' '; + std::ostream& os = std::cout; - const short isParityOn = distanceSensors.size() % 2; - const short stringNums = distanceSensors.size() / 2; - os << "Distance sensors:" << std::endl; - auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& - { - while(num > 0) - { - s << c; - num--; - } - return s; - }; - if (isParityOn) - { - printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << - distanceSensors[stringNums] << std::endl; - } - for (short i = 0; i < stringNums; ++i) - { - printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << - std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; - printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << - distanceSensors[stringNums + i + isParityOn - 1] << std::endl; - } + const short isParityOn = distanceSensors.size() % 2; + const short stringNums = distanceSensors.size() / 2; + os << "Distance sensors:" << std::endl; + const auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& + { + while (num > 0) + { + s << c; + num--; + } + return s; + }; + if (isParityOn) + { + printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << + distanceSensors[stringNums] << std::endl; + } + for (short i = 0; i < stringNums; ++i) + { + printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << + std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; + printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << + distanceSensors[stringNums + i + isParityOn - 1] << std::endl; + } } +} + +void SensorsViewer::showLineInfo() +{ if (!lineSensors.empty()) { std::cout << "Line sensors:" << std::endl; std::cout << "|"; @@ -53,25 +48,27 @@ void SensorsViewer::show() { std::cout << "|" << std::endl; } } + +void SensorsViewer::setData(const std::vector& d, SensorType t) { + if (t == LINE_SENSORS) { + lineSensors = d; + } + else { + distanceSensors = d; + } +} + +void SensorsViewer::show() { + if (system("clear")) system("cls"); + showDistanceInfo(); + showLineInfo(); +} void SensorsViewer::show(SensorType type) { if (type == LINE_SENSORS) { - if (!lineSensors.empty()) { - std::cout << "\r" << "|"; - for (unsigned int i = 0; i < lineSensors.size(); i++) { - std::cout << (lineSensors[i] ? "@@@" : " "); - } - std::cout << "|"; - } + showLineInfo(); } else { - if (!distanceSensors.empty()) { - if (system("clear")) system("cls"); - std::cout << "Distance sensors:" << std::endl; - if (distanceSensors.size() >= 1) std::cout << " " << std::setw(4) << distanceSensors[0] << std::endl; - if (distanceSensors.size() >= 2) std::cout << " " << std::setw(4) << distanceSensors[1] << (distanceSensors.size() == 2 ? "\n" : ""); - if (distanceSensors.size() >= 3) std::cout << " " << std::setw(4) << distanceSensors[2] << std::endl; - if (distanceSensors.size() >= 4) std::cout << " " << std::setw(4) << distanceSensors[3] << (distanceSensors.size() == 4 ? "\n" : ""); - if (distanceSensors.size() >= 5) std::cout << " " << std::setw(4) << distanceSensors[4] << std::endl; - } + if (system("clear")) system("cls"); + showDistanceInfo(); } } \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.h b/code/c++/cxx-gamepad-app/SensorsViewer.h index 365b345..c343f27 100644 --- a/code/c++/cxx-gamepad-app/SensorsViewer.h +++ b/code/c++/cxx-gamepad-app/SensorsViewer.h @@ -12,6 +12,9 @@ class SensorsViewer { std::vector lineSensors; std::vector distanceSensors; + void showDistanceInfo(); + void showLineInfo(); + public: void setData(const std::vector& d, SensorType t); void show(); From a9d8ee806a0d947cdd2ed35cceed098d96f38b3f Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 31 Aug 2017 23:04:42 +0300 Subject: [PATCH 104/336] =?UTF-8?q?SensorsViewer=20=D0=B2=D1=8B=D0=BD?= =?UTF-8?q?=D0=B5=D1=81=D0=B5=D0=BD=D0=B0=20=D0=B2=20=D0=BE=D1=82=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D1=83=D1=8E=20=D0=B1=D0=B8=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D0=BE=D1=82=D0=B5=D0=BA=D1=83.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=BA=D0=B0=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=D0=BA=D0=B8=20=D0=B4=D0=BB=D1=8F=20cxx-app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/.gitignore | 299 ++++++++++++++++++ code/c++/cxx-app/cxx-app.sln | 13 +- code/c++/cxx-app/cxx-app.vcxproj | 20 +- code/c++/cxx-app/cxx-app.vcxproj.filters | 8 - code/c++/cxx-app/makefile | 19 +- code/c++/cxx-gamepad-app/SensorsViewer.cpp | 74 ----- code/c++/cxx-gamepad-app/SensorsViewer.h | 22 -- .../SensorsViewer.cpp | 0 .../{cxx-app => cxx-library}/SensorsViewer.h | 0 code/c++/cxx-library/cxx-library.vcxproj | 154 +++++++++ .../cxx-library/cxx-library.vcxproj.filters | 27 ++ code/c++/cxx-library/makefile | 140 ++++++++ 12 files changed, 655 insertions(+), 121 deletions(-) create mode 100644 code/c++/.gitignore delete mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.cpp delete mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.h rename code/c++/{cxx-app => cxx-library}/SensorsViewer.cpp (100%) rename code/c++/{cxx-app => cxx-library}/SensorsViewer.h (100%) create mode 100644 code/c++/cxx-library/cxx-library.vcxproj create mode 100644 code/c++/cxx-library/cxx-library.vcxproj.filters create mode 100644 code/c++/cxx-library/makefile diff --git a/code/c++/.gitignore b/code/c++/.gitignore new file mode 100644 index 0000000..1d434d3 --- /dev/null +++ b/code/c++/.gitignore @@ -0,0 +1,299 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# AJIOB_Exclude +Output +Build* diff --git a/code/c++/cxx-app/cxx-app.sln b/code/c++/cxx-app/cxx-app.sln index d3c2d65..90d95cf 100644 --- a/code/c++/cxx-app/cxx-app.sln +++ b/code/c++/cxx-app/cxx-app.sln @@ -1,15 +1,18 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.13 +VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-app", "cxx-app.vcxproj", "{F92E7862-33C4-48B8-A055-3EE00352161F}" ProjectSection(ProjectDependencies) = postProject + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA} = {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA} {32D3778A-E59E-4DBC-8D86-BD23B708CA12} = {32D3778A-E59E-4DBC-8D86-BD23B708CA12} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-api", "..\cxx-api\cxx-api.vcxproj", "{32D3778A-E59E-4DBC-8D86-BD23B708CA12}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-library", "..\cxx-library\cxx-library.vcxproj", "{57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -34,6 +37,14 @@ Global {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x64.Build.0 = Release|x64 {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.ActiveCfg = Release|Win32 {32D3778A-E59E-4DBC-8D86-BD23B708CA12}.Release|x86.Build.0 = Release|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x64.ActiveCfg = Debug|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x64.Build.0 = Debug|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x86.ActiveCfg = Debug|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x86.Build.0 = Debug|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x64.ActiveCfg = Release|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x64.Build.0 = Release|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x86.ActiveCfg = Release|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/code/c++/cxx-app/cxx-app.vcxproj b/code/c++/cxx-app/cxx-app.vcxproj index 32a43a6..07045c9 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj +++ b/code/c++/cxx-app/cxx-app.vcxproj @@ -71,21 +71,21 @@ true - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ true - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ false - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ @@ -93,7 +93,7 @@ false $(SolutionDir)Output\$(Configuration)-$(Platform)\;$(OutDir);$(LibraryPath) - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) + $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api\serial_support\include;$(IncludePath) $(SolutionDir)Output\$(Configuration)-$(Platform)\ $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ @@ -109,7 +109,7 @@ Console - cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-api.lib;cxx-library.lib; @@ -124,7 +124,7 @@ Console - cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-api.lib;cxx-library.lib; @@ -143,7 +143,7 @@ Console true true - cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-api.lib;cxx-library.lib; @@ -162,15 +162,11 @@ Console true true - cxx-api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-api.lib;cxx-library.lib; - - - - diff --git a/code/c++/cxx-app/cxx-app.vcxproj.filters b/code/c++/cxx-app/cxx-app.vcxproj.filters index 823c170..0d8d9e4 100644 --- a/code/c++/cxx-app/cxx-app.vcxproj.filters +++ b/code/c++/cxx-app/cxx-app.vcxproj.filters @@ -18,13 +18,5 @@ Source Files - - Source Files - - - - - Header Files - \ No newline at end of file diff --git a/code/c++/cxx-app/makefile b/code/c++/cxx-app/makefile index 63ca49d..ce7d227 100644 --- a/code/c++/cxx-app/makefile +++ b/code/c++/cxx-app/makefile @@ -56,15 +56,22 @@ API_PATH = ../cxx-api API_INCLUDE_PATH = $(API_PATH) API_BUILD_PATH = $(API_PATH)/$(BUILD_PATH) +CXX_LIB_PATH = ../cxx-library +CXX_LIB_INCLUDE_PATH = $(CXX_LIB_PATH) +CXX_LIB_BUILD_PATH = $(CXX_LIB_PATH)/$(BUILD_PATH) + ifeq ($(BUILD), BUILD_STATIC) API_NAME = track-platform_cxx-api.a +CXX_LIB_NAME = track-platform_cxx-library.a else ifeq ($(BUILD), BUILD_DYNAMIC) API_NAME = track-platform_cxx-api.so +CXX_LIB_NAME = track-platform_cxx-library.so endif endif API_FULL_PATH = $(API_BUILD_PATH)/$(API_NAME) +CXX_LIB_FULL_PATH = $(CXX_LIB_BUILD_PATH)/$(CXX_LIB_NAME) #Linker scrpit file ARFLAGS = @@ -74,11 +81,11 @@ ARFLAGS = SOURCES = # Other code (non grouped) SOURCES += $(OTHER_SOURCE_PATH)/main.cpp -SOURCES += $(OTHER_SOURCE_PATH)/SensorsViewer.cpp #Include file path INCLUDES = INCLUDES += -I$(API_INCLUDE_PATH) +INCLUDES += -I$(CXX_LIB_INCLUDE_PATH) # INCLUDES += -I$(OTHER_INCLUDE_PATH) ############################################################################################################## @@ -89,11 +96,11 @@ BIN = $(BUILD_PATH)/$(PROJECT_NAME) OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) -STATIC_LIB: $(OBJECTS) api - @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) +STATIC_LIB: $(OBJECTS) api library + @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) $(CXX_LIB_FULL_PATH) @echo -e "$(BUILD_PRINT)" -DYNAMIC_LIB: $(OBJECTS) api +DYNAMIC_LIB: $(OBJECTS) api librarylibrary $(error Dynamic library is not supported yet) # @$(CXX) -shared -o $(BIN) $(OBJECTS) @echo -e "$(BUILD_PRINT)" @@ -135,9 +142,13 @@ static: api: $(MAKE) -C $(API_PATH) BUILD=$(BUILD) +library: + $(MAKE) -C $(CXX_LIB_PATH) BUILD=$(BUILD) + clean: @rm -rf $(BUILD_PATH) $(MAKE) -C $(API_PATH) $@ + $(MAKE) -C $(CXX_LIB_PATH) $@ run: @$(BIN) diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.cpp b/code/c++/cxx-gamepad-app/SensorsViewer.cpp deleted file mode 100644 index 4e9ec81..0000000 --- a/code/c++/cxx-gamepad-app/SensorsViewer.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "SensorsViewer.h" - -void SensorsViewer::showDistanceInfo() -{ - if (!distanceSensors.empty()) { - //configuration - const short prefixSymbolNum = 1; - const short betweenSymbolNum = 1; - const short oneNumMinSize = 4; - const char delimiter = ' '; - std::ostream& os = std::cout; - - const short isParityOn = distanceSensors.size() % 2; - const short stringNums = distanceSensors.size() / 2; - os << "Distance sensors:" << std::endl; - const auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& - { - while (num > 0) - { - s << c; - num--; - } - return s; - }; - if (isParityOn) - { - printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << - distanceSensors[stringNums] << std::endl; - } - for (short i = 0; i < stringNums; ++i) - { - printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << - std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; - printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << - distanceSensors[stringNums + i + isParityOn - 1] << std::endl; - } - } -} - -void SensorsViewer::showLineInfo() -{ - if (!lineSensors.empty()) { - std::cout << "Line sensors:" << std::endl; - std::cout << "|"; - for (unsigned int i = 0; i < lineSensors.size(); i++) { - std::cout << (lineSensors[i] ? "@@@" : " "); - } - std::cout << "|" << std::endl; - } -} - -void SensorsViewer::setData(const std::vector& d, SensorType t) { - if (t == LINE_SENSORS) { - lineSensors = d; - } - else { - distanceSensors = d; - } -} - -void SensorsViewer::show() { - if (system("clear")) system("cls"); - showDistanceInfo(); - showLineInfo(); -} -void SensorsViewer::show(SensorType type) { - if (type == LINE_SENSORS) { - showLineInfo(); - } - else { - if (system("clear")) system("cls"); - showDistanceInfo(); - } -} \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.h b/code/c++/cxx-gamepad-app/SensorsViewer.h deleted file mode 100644 index c343f27..0000000 --- a/code/c++/cxx-gamepad-app/SensorsViewer.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include -#include -#include -#include - -enum SensorType { - LINE_SENSORS, DISTANCE_SENSORS -}; - -class SensorsViewer { - std::vector lineSensors; - std::vector distanceSensors; - - void showDistanceInfo(); - void showLineInfo(); - -public: - void setData(const std::vector& d, SensorType t); - void show(); - void show(SensorType type); -}; \ No newline at end of file diff --git a/code/c++/cxx-app/SensorsViewer.cpp b/code/c++/cxx-library/SensorsViewer.cpp similarity index 100% rename from code/c++/cxx-app/SensorsViewer.cpp rename to code/c++/cxx-library/SensorsViewer.cpp diff --git a/code/c++/cxx-app/SensorsViewer.h b/code/c++/cxx-library/SensorsViewer.h similarity index 100% rename from code/c++/cxx-app/SensorsViewer.h rename to code/c++/cxx-library/SensorsViewer.h diff --git a/code/c++/cxx-library/cxx-library.vcxproj b/code/c++/cxx-library/cxx-library.vcxproj new file mode 100644 index 0000000..99d63ed --- /dev/null +++ b/code/c++/cxx-library/cxx-library.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 15.0 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA} + Win32Proj + cxxlibrary + 8.1 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + $(SolutionDir)Output\$(Configuration)-$(Platform)\ + $(SolutionDir)Build\$(ProjectName)\$(Configuration)-$(Platform)\ + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/code/c++/cxx-library/cxx-library.vcxproj.filters b/code/c++/cxx-library/cxx-library.vcxproj.filters new file mode 100644 index 0000000..6b708b4 --- /dev/null +++ b/code/c++/cxx-library/cxx-library.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/code/c++/cxx-library/makefile b/code/c++/cxx-library/makefile new file mode 100644 index 0000000..db0cec3 --- /dev/null +++ b/code/c++/cxx-library/makefile @@ -0,0 +1,140 @@ +#Make file to compile source code for track platform cxx api library + +#Project Name +PROJECT_NAME = track-platform_cxx-library +#Build option +BUILD ?= BUILD_STATIC +#ANSI Colos +ANSI_COLOR_RED = \e[31m +ANSI_COLOR_GREEN = \e[32m +ANSI_COLOR_YELLOW = \e[33m +ANSI_COLOR_BLUE = \e[34m +ANSI_COLOR_MAGENTA = \e[35m +ANSI_COLOR_CYAN = \e[36m +ANSI_COLOR_RESET = \e[37m +################################Compiller flags############################################################### +#Opitmization Level +OPT_LEVEL = -O0 +#Warning options +WARNINGS = -Wall -Wpedantic #-Werror +# WARNINGS += -fsyntax-only # for syntax checking only, without comlipation +WARNINGS_WITHOUT = +#User Compiller flags +USER_FLAGS ?= +############################################################################################################## +# OS redefinition +OS = $(shell uname -s) +ifeq ($(OS), Linux) +OS = linux +endif + +#Build patch +BUILD_PATH = Output/$(OS) +OBJ_PATH = $(BUILD_PATH)/obj + +#Compiller flags +CFLAGS = $(OPT_LEVEL) +CFLAGS += -g0 +CFLAGS += $(WARNINGS) +CFLAGS += -I. +CFLAGS += $(USER_FLAGS) +CFLAGS += -std=c++11 +CFLAGS += -D$(BUILD) +# ifeq ($(BUILD), BUILD_STATIC) +# CFLAGS += -D$(BUILD_STATIC) +# endif + +CFLAGS += $(INCLUDES) +############################################################################################################## +#Code file path +OTHER_PATH = . +OTHER_SOURCE_PATH = $(OTHER_PATH) +OTHER_INCLUDE_PATH = $(OTHER_PATH) + +#Linker scrpit file +ARFLAGS = -cvq + +#Source file path + +SOURCES = +# Other code (non grouped) +SOURCES += $(OTHER_SOURCE_PATH)/SensorsViewer.cpp + +#Include file path +INCLUDES = +# INCLUDES += -I$(OTHER_INCLUDE_PATH) + +############################################################################################################## +BUILD_PRINT = $(ANSI_COLOR_GREEN) Building:$(ANSI_COLOR_RESET) $@ +############################################################################################################## +#Output files +STATIC_LIB = $(BUILD_PATH)/$(PROJECT_NAME).a +DYNAMIC_LIB = $(BUILD_PATH)/$(PROJECT_NAME).so + +OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) + +$(STATIC_LIB): $(OBJECTS) + @$(AR) $(ARFLAGS) $@ $(OBJECTS) + @echo -e "$(BUILD_PRINT)" + +$(DYNAMIC_LIB): $(OBJECTS) +# $(error Dynamic library is not supported yet) + @$(CXX) -shared -o $@ $(OBJECTS) + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cc + @mkdir -p $(dir $@) + +ifeq ($(BUILD), BUILD_DYNAMIC) + @$(CXX) -fPIC -c $(CFLAGS) $< -o $@ +else + @$(CXX) -c $(CFLAGS) $< -o $@ +endif + @echo -e "$(BUILD_PRINT)" + +$(OBJ_PATH)/%.o: %.cpp + @mkdir -p $(dir $@) + +ifeq ($(BUILD), BUILD_DYNAMIC) + @$(CXX) -fPIC -c $(CFLAGS) $< -o $@ +else + @$(CXX) -c $(CFLAGS) $< -o $@ +endif + @echo -e "$(BUILD_PRINT)" + +#Makefile parameters +.DEFAULT_GOAL := all + +all: build + +ifeq ($(BUILD), BUILD_STATIC) +build: $(STATIC_LIB) + +else +ifeq ($(BUILD), BUILD_DYNAMIC) +build: $(DYNAMIC_LIB) + +else +build: + @echo "That BUILD variable is not supported. Use `make help` to see supported variants of build variable" +endif +endif + +dynamic: + $(MAKE) BUILD=BUILD_DYNAMIC + +static: + $(MAKE) BUILD=BUILD_STATIC + +clean: + @rm -rf $(BUILD_PATH) + +set_def_color: + @echo -e "$(ANSI_COLOR_RESET)" + +help: + @echo "$(NEW_LINE)" + @echo "\tall : Builds static or dynamic library (static by default)" + @echo "\t\tIf you want to build static library(.a file), write `make` or `make static` or `make BUILD=BUILD_DYNAMIC`" + @echo "\t\tIf you want to build dynamic library(.so file), write `make dynamic` or `make BUILD=BUILD_DYNAMIC`" + @echo "$(NEW_LINE)" From 56f63faef35c9af72a84ebd8f8cdc94befdf8090 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 31 Aug 2017 23:28:38 +0300 Subject: [PATCH 105/336] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=20=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20api-v2=20=D0=B2=D1=8B=D0=BD?= =?UTF-8?q?=D0=B5=D1=81=D0=B5=D0=BD=20=D1=81=20BasicConnector=20(=D1=82.?= =?UTF-8?q?=D0=B5.=20=D1=81=D0=BA=D1=80=D1=8B=D1=82=20=D0=BE=D1=82=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20=D1=83=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cxx-api/TrackPlatform_BasicConnector.cpp | 47 +++++++++---------- .../cxx-api/TrackPlatform_BasicConnector.h | 2 +- .../cxx-api/TrackPlatform_BasicManagement.cpp | 3 -- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index 0b8673e..fe793a3 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -10,34 +10,13 @@ const char TrackPlatform_BasicConnector::stopSymbol; const uint8_t TrackPlatform_BasicConnector::timesToAutoreconnect; const uint32_t TrackPlatform_BasicConnector::timeoutToNextConnectInMs; -const std::string TrackPlatform_BasicConnector::connectedAnswer = "OK"; +const std::string TrackPlatform_BasicConnector::correctAnswer = "OK"; void TrackPlatform_BasicConnector::sendStartCommand() { std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(APIWithAnswer); isConnectedToArduino = true; - for (auto i = 0; i < timesToAutoreconnect; ++i) - { - Logger::log("Trying to connect to arduino. Attempt " + std::to_string(i + 1)); - sendOneCommand(command); - try { - if (readOneAnswer() == connectedAnswer) - { - Logger::log("Connected successfully"); - return; - } - } - catch(CorruptedAnswerException&) - { - //All is good, module not answered, try again - } - - std::this_thread::sleep_for(std::chrono::milliseconds(timeoutToNextConnectInMs)); - } - - isConnectedToArduino = false; - Logger::log("Cannot connect to arduino"); - throw CannotConnectToArduinoException(); + sendOneCommand(command); } void TrackPlatform_BasicConnector::sendStopCommand() { @@ -73,8 +52,28 @@ void TrackPlatform_BasicConnector::sendOneCommand(const std::string& s) { throw NoConnectionException(); } - write(s + stopSymbol); Logger::log("Send: " + s + stopSymbol); + for (auto i = 0; i < timesToAutoreconnect; ++i) + { + Logger::log("Trying to send command. Attempt " + std::to_string(i + 1)); + write(s + stopSymbol); + try { + if (readOneAnswer() == correctAnswer) + { + Logger::log("Sending successfully"); + return; + } + } + catch (CorruptedAnswerException&) + { + //All is good, module not answered, try again + } + std::this_thread::sleep_for(std::chrono::milliseconds(timeoutToNextConnectInMs)); + } + + isConnectedToArduino = false; + Logger::log("Cannot connect to arduino"); + throw CannotConnectToArduinoException(); } bool TrackPlatform_BasicConnector::isConnected() diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index 68f189f..12370dd 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -11,7 +11,7 @@ class TrackPlatform_BasicConnector static const char stopSymbol = '|'; static const uint8_t timesToAutoreconnect = 3; static const uint32_t timeoutToNextConnectInMs = 500; - static const std::string connectedAnswer; + static const std::string correctAnswer; virtual void write(const std::string& s) = 0; virtual std::string read() = 0; diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 97157cf..bc0c54f 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -4,7 +4,6 @@ void TrackPlatform_BasicManagement::sendMove(const std::string& additionalInfo) { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(movementControllerID) + additionalInfo); - auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } @@ -12,7 +11,6 @@ void TrackPlatform_BasicManagement::sendSensors(const std::string& additionalInf { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(sensorsControllerID) + additionalInfo); - auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } @@ -20,7 +18,6 @@ void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(servoControllerID) + additionalInfo); - auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } From c1d21961e256608dc1c69eee33c2b1911b13d5bb Mon Sep 17 00:00:00 2001 From: Kimentii Date: Sun, 3 Sep 2017 13:53:51 +0300 Subject: [PATCH 106/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=B0=D0=B2=D1=82=D0=BE=D1=81=D0=BE=D0=B5?= =?UTF-8?q?=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=B0=D0=B6?= =?UTF-8?q?=D0=B4=D1=83=D1=8E=20=D1=81=D0=B5=D0=BA=D1=83=D0=BD=D0=B4=D1=83?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/AutoConnector.cpp | 40 ++++++++++++++++++++++++ code/c++/cxx-api/AutoConnector.h | 28 +++++++++++++++++ code/c++/cxx-api/cxx-api.vcxproj | 2 ++ code/c++/cxx-api/cxx-api.vcxproj.filters | 6 ++++ code/c++/cxx-app/main.cpp | 5 ++- 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 code/c++/cxx-api/AutoConnector.cpp create mode 100644 code/c++/cxx-api/AutoConnector.h diff --git a/code/c++/cxx-api/AutoConnector.cpp b/code/c++/cxx-api/AutoConnector.cpp new file mode 100644 index 0000000..f3a8859 --- /dev/null +++ b/code/c++/cxx-api/AutoConnector.cpp @@ -0,0 +1,40 @@ +#include "AutoConnector.h" + +unsigned int threadFun(Data* data) { + while ((data->pIsRepeat)->load()) { + uint32_t startTime = clock(); + uint32_t endTime = startTime + ((double)data->frequency) / 1000 * CLOCKS_PER_SEC; + while (clock() < endTime && (data->pIsRepeat)->load()) { + Sleep(1); + } + data->pTrackPlatform->sensorLineGetAllValues(); + } + return 0; +} + +AutoConnector::AutoConnector(TrackPlatform_Manager& tp, uint32_t f) : pTrackPlatform(&tp), frequency(f) { + isRepeat.store(false); +} + +void AutoConnector::start() { + if (!isRepeat.load()) + { + Data *d = new Data(); + d->pIsRepeat = &isRepeat; + d->pTrackPlatform = pTrackPlatform; + d->frequency = frequency; + isRepeat.store(true); + connectingThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&threadFun, (LPVOID)d, 0, NULL); + } +} + +void AutoConnector::stop() { + if (isRepeat.load()) { + isRepeat.store(false); + WaitForSingleObject(connectingThread, INFINITE); + } +} + +bool AutoConnector::isConnecting() { + return isRepeat.load(); +} \ No newline at end of file diff --git a/code/c++/cxx-api/AutoConnector.h b/code/c++/cxx-api/AutoConnector.h new file mode 100644 index 0000000..c4f2203 --- /dev/null +++ b/code/c++/cxx-api/AutoConnector.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include +#include +#include "TrackPlatform_Manager.h" + +struct Data { + std::atomic_bool* pIsRepeat; + TrackPlatform_Manager* pTrackPlatform; + uint32_t frequency; +}; +unsigned int threadFun(Data* data); + +class AutoConnector { +private: + HANDLE connectingThread; + TrackPlatform_Manager* pTrackPlatform; + std::atomic_bool isRepeat; + uint32_t frequency; + +public: + AutoConnector(TrackPlatform_Manager& tp, uint32_t f = reconnectTime); + void start(); + void stop(); + bool isConnecting(); + static const uint32_t reconnectTime = 1000; +}; \ No newline at end of file diff --git a/code/c++/cxx-api/cxx-api.vcxproj b/code/c++/cxx-api/cxx-api.vcxproj index 8c75329..76781da 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj +++ b/code/c++/cxx-api/cxx-api.vcxproj @@ -146,6 +146,7 @@ + @@ -171,6 +172,7 @@ + diff --git a/code/c++/cxx-api/cxx-api.vcxproj.filters b/code/c++/cxx-api/cxx-api.vcxproj.filters index 8ee1d7e..3fe8847 100644 --- a/code/c++/cxx-api/cxx-api.vcxproj.filters +++ b/code/c++/cxx-api/cxx-api.vcxproj.filters @@ -111,6 +111,9 @@ exceptions\header + + Communication\header + @@ -143,5 +146,8 @@ Source Files + + Communication\source + \ No newline at end of file diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index c09cf6f..1df1a2f 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -10,6 +10,7 @@ #include "TrackPlatform_Manager.h" #include "SensorsViewer.h" +#include "AutoConnector.h" int main(int argc, char* argv[]) { @@ -45,7 +46,8 @@ int main(int argc, char* argv[]) TrackPlatform_Manager trackPlatform(WiFi, info); #endif - + AutoConnector autoConnector(trackPlatform, AutoConnector::reconnectTime); + autoConnector.start(); bool isExit = false; while (!isExit) { @@ -73,6 +75,7 @@ int main(int argc, char* argv[]) std::cout << "h: set vertical servo angle in degree" << std::endl; break; case 'q': + autoConnector.stop(); isExit = true; break; case 'w': From 0e6e90fc0349e199376ab7ae0081f30231b404ee Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 4 Sep 2017 13:54:49 +0300 Subject: [PATCH 107/336] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D0=BE=20=D0=BA=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=81=D0=BF=D0=BB=D0=B0=D1=82=D1=84=D0=BE=D1=80=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/AutoConnector.cpp | 33 ++++++++----------- code/c++/cxx-api/AutoConnector.h | 15 ++++----- code/c++/cxx-api/CommandsEnum.h | 1 + .../cxx-api/TrackPlatform_BasicManagement.cpp | 12 +++++++ .../cxx-api/TrackPlatform_BasicManagement.h | 4 +++ code/c++/cxx-api/TrackPlatform_Manager.cpp | 13 +++++++- code/c++/cxx-api/TrackPlatform_Manager.h | 5 +++ 7 files changed, 54 insertions(+), 29 deletions(-) diff --git a/code/c++/cxx-api/AutoConnector.cpp b/code/c++/cxx-api/AutoConnector.cpp index f3a8859..4c41066 100644 --- a/code/c++/cxx-api/AutoConnector.cpp +++ b/code/c++/cxx-api/AutoConnector.cpp @@ -1,37 +1,32 @@ #include "AutoConnector.h" -unsigned int threadFun(Data* data) { - while ((data->pIsRepeat)->load()) { - uint32_t startTime = clock(); - uint32_t endTime = startTime + ((double)data->frequency) / 1000 * CLOCKS_PER_SEC; - while (clock() < endTime && (data->pIsRepeat)->load()) { - Sleep(1); - } - data->pTrackPlatform->sensorLineGetAllValues(); - } - return 0; -} - -AutoConnector::AutoConnector(TrackPlatform_Manager& tp, uint32_t f) : pTrackPlatform(&tp), frequency(f) { +AutoConnector::AutoConnector(std::function c, uint32_t f) : callback(c), frequency(f) { isRepeat.store(false); } void AutoConnector::start() { if (!isRepeat.load()) { - Data *d = new Data(); - d->pIsRepeat = &isRepeat; - d->pTrackPlatform = pTrackPlatform; - d->frequency = frequency; + Data d; + d.callback = callback; + d.pIsRepeat = &isRepeat; + d.frequency = frequency; isRepeat.store(true); - connectingThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&threadFun, (LPVOID)d, 0, NULL); + pConnectingThread = new std::thread([d]() { + while (d.pIsRepeat->load()) + { + d.callback(); + std::this_thread::sleep_for(std::chrono::milliseconds(d.frequency)); + } + }); } } void AutoConnector::stop() { if (isRepeat.load()) { isRepeat.store(false); - WaitForSingleObject(connectingThread, INFINITE); + pConnectingThread->join(); + delete pConnectingThread; } } diff --git a/code/c++/cxx-api/AutoConnector.h b/code/c++/cxx-api/AutoConnector.h index c4f2203..f869bb9 100644 --- a/code/c++/cxx-api/AutoConnector.h +++ b/code/c++/cxx-api/AutoConnector.h @@ -1,28 +1,25 @@ #pragma once #include -#include -#include #include -#include "TrackPlatform_Manager.h" +#include +#include struct Data { + std::function callback; std::atomic_bool* pIsRepeat; - TrackPlatform_Manager* pTrackPlatform; uint32_t frequency; }; -unsigned int threadFun(Data* data); class AutoConnector { private: - HANDLE connectingThread; - TrackPlatform_Manager* pTrackPlatform; + std::thread* pConnectingThread; + std::function callback; std::atomic_bool isRepeat; uint32_t frequency; public: - AutoConnector(TrackPlatform_Manager& tp, uint32_t f = reconnectTime); + AutoConnector(std::function c, uint32_t f = 500); void start(); void stop(); bool isConnecting(); - static const uint32_t reconnectTime = 1000; }; \ No newline at end of file diff --git a/code/c++/cxx-api/CommandsEnum.h b/code/c++/cxx-api/CommandsEnum.h index 5a1f9cf..4f9fbee 100644 --- a/code/c++/cxx-api/CommandsEnum.h +++ b/code/c++/cxx-api/CommandsEnum.h @@ -48,6 +48,7 @@ enum ServoCommands { enum CommunicationCommands { startCommunicationCommand = 1, //starting communication command stopCommunicationCommand = 2, //stopping communication command + refreshConnectionCommunicationCommand = 3, //refreshing connection timer communication command (since API v3) }; /** diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index 97157cf..21d1a32 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -24,6 +24,13 @@ void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) readWriteAtomicMutex.unlock(); } +void TrackPlatform_BasicManagement::sendCommunication(const std::string& additionalInfo) { + readWriteAtomicMutex.lock(); + connector->sendOneCommand(static_cast(communicationControllerID) + additionalInfo); + auto answer = connector->readOneAnswer(); + readWriteAtomicMutex.unlock(); +} + std::vector TrackPlatform_BasicManagement::parseStringToArray(std::string s) { std::vector distancies; @@ -221,3 +228,8 @@ std::vector TrackPlatform_BasicManagement::servoGetAngles() readWriteAtomicMutex.unlock(); return parseStringToArray(answer); } + +void TrackPlatform_BasicManagement::refreshConnection() { + std::string toSend(1, refreshConnectionCommunicationCommand); + sendCommunication(toSend); +} \ No newline at end of file diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index c4d0020..d3a716a 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -19,6 +19,7 @@ class TrackPlatform_BasicManagement void sendMove(const std::string& additionalInfo); void sendSensors(const std::string& additionalInfo); void sendServo(const std::string& additionalInfo); + void sendCommunication(const std::string& additionalInfo); static std::vector parseStringToArray(std::string s); @@ -59,6 +60,9 @@ class TrackPlatform_BasicManagement void servoSetVerticalAngle(uint16_t angle); void servoSetHorizontalVerticalAngle(uint16_t horizontalAngle, uint16_t verticalAngle); std::vector servoGetAngles(); + + /* connection */ + void refreshConnection(); }; #endif /* _TRACKPLATFORM_BASICMANAGEMENT_H_ */ diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index 2ad92f4..7f42ee6 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -24,9 +24,12 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne return res; } -TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info) : +TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info) : TrackPlatform_BasicManagement(createConnectorByMode(mode, info)) { + std::function callback = [this]() { this->refreshConnection(); }; + pAutoConnector = new AutoConnector(callback); + pAutoConnector->start(); } TrackPlatform_Manager::~TrackPlatform_Manager() @@ -36,4 +39,12 @@ TrackPlatform_Manager::~TrackPlatform_Manager() { delete connector; } + if (pAutoConnector) delete pAutoConnector; } + +void TrackPlatform_Manager::startAutoConnection() { + pAutoConnector->start(); +} +void TrackPlatform_Manager::stopAutoConnection() { + pAutoConnector->stop(); +} \ No newline at end of file diff --git a/code/c++/cxx-api/TrackPlatform_Manager.h b/code/c++/cxx-api/TrackPlatform_Manager.h index cd478e4..a385505 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.h +++ b/code/c++/cxx-api/TrackPlatform_Manager.h @@ -4,14 +4,19 @@ #include "TrackPlatform_BasicManagement.h" #include "ConnectionModes.h" #include "CommunicationInfoStruct.h" +#include "AutoConnector.h" class TrackPlatform_Manager : public TrackPlatform_BasicManagement { static TrackPlatform_BasicConnector* createConnectorByMode(ConnectionModes mode, const CommunicationInfoStruct& info); + AutoConnector* pAutoConnector; public: TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info); ~TrackPlatform_Manager(); + + void startAutoConnection(); + void stopAutoConnection(); }; #endif /* _TRACKPLATFORM_MANAGER_H_ */ From e95027175a31dcc5f12faa51874ec5fe195dddd1 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 4 Sep 2017 20:37:20 +0300 Subject: [PATCH 108/336] Highest API fixing (API v3 connection fixing) --- code/Arduino/peripheral/ConnectionController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Arduino/peripheral/ConnectionController.h b/code/Arduino/peripheral/ConnectionController.h index 797e961..1d2c536 100644 --- a/code/Arduino/peripheral/ConnectionController.h +++ b/code/Arduino/peripheral/ConnectionController.h @@ -16,7 +16,7 @@ class ConnectionController static const char disconnectCommand[]; static const char refreshCommand[]; static const StartCommands lowestAPI = startBasicAPI; - static const StartCommands highestAPI = APIWithAnswer; + static const StartCommands highestAPI = APIWithAutoDiconnect; bool isConnected = false; StartCommands connectedAPIversion; From 4b2aaec01a5f4108d4963890076e731924b4ccc5 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 4 Sep 2017 20:40:48 +0300 Subject: [PATCH 109/336] Compilation fix (AutoConnector was removed from main) --- code/c++/cxx-app/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/c++/cxx-app/main.cpp b/code/c++/cxx-app/main.cpp index 1df1a2f..90f81bb 100644 --- a/code/c++/cxx-app/main.cpp +++ b/code/c++/cxx-app/main.cpp @@ -10,7 +10,6 @@ #include "TrackPlatform_Manager.h" #include "SensorsViewer.h" -#include "AutoConnector.h" int main(int argc, char* argv[]) { @@ -46,8 +45,6 @@ int main(int argc, char* argv[]) TrackPlatform_Manager trackPlatform(WiFi, info); #endif - AutoConnector autoConnector(trackPlatform, AutoConnector::reconnectTime); - autoConnector.start(); bool isExit = false; while (!isExit) { @@ -75,7 +72,6 @@ int main(int argc, char* argv[]) std::cout << "h: set vertical servo angle in degree" << std::endl; break; case 'q': - autoConnector.stop(); isExit = true; break; case 'w': From 557effe2b924c87b0de80d31fdf9f12723f3e330 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 4 Sep 2017 21:14:11 +0300 Subject: [PATCH 110/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/TrackPlatform_BasicManagement.h | 3 ++- code/c++/cxx-api/TrackPlatform_Manager.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index d3a716a..6e8d6a5 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -11,11 +11,12 @@ class TrackPlatform_BasicManagement { TrackPlatform_BasicConnector* connector; +protected: static const uint8_t minSpeed = 0; static const uint8_t maxSpeed = 255; + static const uint32_t reconnectTime = 500; static const char delimiter = ';'; -protected: void sendMove(const std::string& additionalInfo); void sendSensors(const std::string& additionalInfo); void sendServo(const std::string& additionalInfo); diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index 7f42ee6..4228a64 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -28,7 +28,7 @@ TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const Communi TrackPlatform_BasicManagement(createConnectorByMode(mode, info)) { std::function callback = [this]() { this->refreshConnection(); }; - pAutoConnector = new AutoConnector(callback); + pAutoConnector = new AutoConnector(callback, reconnectTime); pAutoConnector->start(); } From 11c86e90ae0b6da7611074cd19785a082e2f7aba Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 4 Sep 2017 21:26:18 +0300 Subject: [PATCH 111/336] =?UTF-8?q?=D0=9E=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BE?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B7=D1=80=D1=8B=D0=B2=D0=B0=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/AutoConnector.cpp | 4 ++++ code/c++/cxx-api/AutoConnector.h | 1 + code/c++/cxx-api/TrackPlatform_BasicManagement.cpp | 1 - code/c++/cxx-api/TrackPlatform_Manager.cpp | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/code/c++/cxx-api/AutoConnector.cpp b/code/c++/cxx-api/AutoConnector.cpp index 4c41066..7d16374 100644 --- a/code/c++/cxx-api/AutoConnector.cpp +++ b/code/c++/cxx-api/AutoConnector.cpp @@ -4,6 +4,10 @@ AutoConnector::AutoConnector(std::function c, uint32_t f) : callback(c), isRepeat.store(false); } +AutoConnector::~AutoConnector() { + stop(); +} + void AutoConnector::start() { if (!isRepeat.load()) { diff --git a/code/c++/cxx-api/AutoConnector.h b/code/c++/cxx-api/AutoConnector.h index f869bb9..5c0be5e 100644 --- a/code/c++/cxx-api/AutoConnector.h +++ b/code/c++/cxx-api/AutoConnector.h @@ -19,6 +19,7 @@ class AutoConnector { public: AutoConnector(std::function c, uint32_t f = 500); + ~AutoConnector(); void start(); void stop(); bool isConnecting(); diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp index b1a7f6f..95ea3a9 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.cpp @@ -24,7 +24,6 @@ void TrackPlatform_BasicManagement::sendServo(const std::string& additionalInfo) void TrackPlatform_BasicManagement::sendCommunication(const std::string& additionalInfo) { readWriteAtomicMutex.lock(); connector->sendOneCommand(static_cast(communicationControllerID) + additionalInfo); - auto answer = connector->readOneAnswer(); readWriteAtomicMutex.unlock(); } diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index 4228a64..ec3b710 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -34,12 +34,12 @@ TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const Communi TrackPlatform_Manager::~TrackPlatform_Manager() { + if (pAutoConnector) delete pAutoConnector; TrackPlatform_BasicConnector* connector = getConnector(); if (connector) { delete connector; } - if (pAutoConnector) delete pAutoConnector; } void TrackPlatform_Manager::startAutoConnection() { From 615c19f92b39be3d1febad541bc5b99603b1d8b8 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 4 Sep 2017 21:49:18 +0300 Subject: [PATCH 112/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB?= =?UTF-8?q?=D1=8F=D1=86=D0=B8=D1=8F=20gamepad-=D0=BA=D0=BB=D0=B8=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=20=D0=BF=D0=BE=D0=B4=20Windows.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/SensorsViewer.cpp | 74 ++++++++++++++++++++++ code/c++/cxx-gamepad-app/SensorsViewer.h | 22 +++++++ 2 files changed, 96 insertions(+) create mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.cpp create mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.h diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.cpp b/code/c++/cxx-gamepad-app/SensorsViewer.cpp new file mode 100644 index 0000000..4e9ec81 --- /dev/null +++ b/code/c++/cxx-gamepad-app/SensorsViewer.cpp @@ -0,0 +1,74 @@ +#include "SensorsViewer.h" + +void SensorsViewer::showDistanceInfo() +{ + if (!distanceSensors.empty()) { + //configuration + const short prefixSymbolNum = 1; + const short betweenSymbolNum = 1; + const short oneNumMinSize = 4; + const char delimiter = ' '; + std::ostream& os = std::cout; + + const short isParityOn = distanceSensors.size() % 2; + const short stringNums = distanceSensors.size() / 2; + os << "Distance sensors:" << std::endl; + const auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& + { + while (num > 0) + { + s << c; + num--; + } + return s; + }; + if (isParityOn) + { + printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << + distanceSensors[stringNums] << std::endl; + } + for (short i = 0; i < stringNums; ++i) + { + printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << + std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; + printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << + distanceSensors[stringNums + i + isParityOn - 1] << std::endl; + } + } +} + +void SensorsViewer::showLineInfo() +{ + if (!lineSensors.empty()) { + std::cout << "Line sensors:" << std::endl; + std::cout << "|"; + for (unsigned int i = 0; i < lineSensors.size(); i++) { + std::cout << (lineSensors[i] ? "@@@" : " "); + } + std::cout << "|" << std::endl; + } +} + +void SensorsViewer::setData(const std::vector& d, SensorType t) { + if (t == LINE_SENSORS) { + lineSensors = d; + } + else { + distanceSensors = d; + } +} + +void SensorsViewer::show() { + if (system("clear")) system("cls"); + showDistanceInfo(); + showLineInfo(); +} +void SensorsViewer::show(SensorType type) { + if (type == LINE_SENSORS) { + showLineInfo(); + } + else { + if (system("clear")) system("cls"); + showDistanceInfo(); + } +} \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.h b/code/c++/cxx-gamepad-app/SensorsViewer.h new file mode 100644 index 0000000..c343f27 --- /dev/null +++ b/code/c++/cxx-gamepad-app/SensorsViewer.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include +#include +#include + +enum SensorType { + LINE_SENSORS, DISTANCE_SENSORS +}; + +class SensorsViewer { + std::vector lineSensors; + std::vector distanceSensors; + + void showDistanceInfo(); + void showLineInfo(); + +public: + void setData(const std::vector& d, SensorType t); + void show(); + void show(SensorType type); +}; \ No newline at end of file From 9315e2282511292de5346391c08eaec870bd57da Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 4 Sep 2017 21:50:20 +0300 Subject: [PATCH 113/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D0=B7=D0=B0=D1=89?= =?UTF-8?q?=D0=B8=D1=82=D0=B0=20=D0=BF=D1=80=D0=B8=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=20=D1=81=20=D0=BF=D0=B0=D0=BC=D1=8F=D1=82?= =?UTF-8?q?=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-api/AutoConnector.cpp | 8 +++++--- code/c++/cxx-api/TrackPlatform_Manager.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/code/c++/cxx-api/AutoConnector.cpp b/code/c++/cxx-api/AutoConnector.cpp index 7d16374..17b8a0e 100644 --- a/code/c++/cxx-api/AutoConnector.cpp +++ b/code/c++/cxx-api/AutoConnector.cpp @@ -1,6 +1,8 @@ #include "AutoConnector.h" -AutoConnector::AutoConnector(std::function c, uint32_t f) : callback(c), frequency(f) { +AutoConnector::AutoConnector(std::function c, uint32_t f) : pConnectingThread(nullptr), callback(c), + frequency(f) +{ isRepeat.store(false); } @@ -9,7 +11,7 @@ AutoConnector::~AutoConnector() { } void AutoConnector::start() { - if (!isRepeat.load()) + if (!isRepeat.load() && !pConnectingThread) { Data d; d.callback = callback; @@ -27,7 +29,7 @@ void AutoConnector::start() { } void AutoConnector::stop() { - if (isRepeat.load()) { + if (isRepeat.load() && pConnectingThread) { isRepeat.store(false); pConnectingThread->join(); delete pConnectingThread; diff --git a/code/c++/cxx-api/TrackPlatform_Manager.h b/code/c++/cxx-api/TrackPlatform_Manager.h index a385505..8cfae12 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.h +++ b/code/c++/cxx-api/TrackPlatform_Manager.h @@ -9,7 +9,7 @@ class TrackPlatform_Manager : public TrackPlatform_BasicManagement { static TrackPlatform_BasicConnector* createConnectorByMode(ConnectionModes mode, const CommunicationInfoStruct& info); - AutoConnector* pAutoConnector; + AutoConnector* pAutoConnector = nullptr; public: TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info); From 73403caa943013540b3a6bdd9f8a3a58775a57b6 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 4 Sep 2017 22:03:45 +0300 Subject: [PATCH 114/336] Debug info about bad command was added --- code/Arduino/peripheral/ConnectionController.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/Arduino/peripheral/ConnectionController.cpp b/code/Arduino/peripheral/ConnectionController.cpp index 4a5310f..99b396d 100644 --- a/code/Arduino/peripheral/ConnectionController.cpp +++ b/code/Arduino/peripheral/ConnectionController.cpp @@ -64,7 +64,8 @@ void ConnectionController::waitForConnection() //check first part of command (if that command is connection command) if (readInfo.length() < sizeof (connectCommand) || (readInfo.substring(0, sizeof(connectCommand) - 1) != connectCommand)) { - DEBUG_PRINTLN("Bad info"); + DEBUG_PRINT("Bad info: "); + DEBUG_PRINTLNHEX(readInfo); continue; } From 65a804422336d364716d4e03c9068f4139bba1cb Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 4 Sep 2017 22:42:26 +0300 Subject: [PATCH 115/336] AutoConnector moved from TrackPlatform_BasicManagement to TrackPlatform_BasicConnector. Secondary use of AutoConnector was added. --- code/c++/cxx-api/AutoConnector.cpp | 1 + code/c++/cxx-api/AutoConnector.h | 2 +- code/c++/cxx-api/TrackPlatform_BasicConnector.cpp | 8 +++++++- code/c++/cxx-api/TrackPlatform_BasicConnector.h | 3 +++ code/c++/cxx-api/TrackPlatform_BasicManagement.h | 1 - code/c++/cxx-api/TrackPlatform_Manager.cpp | 11 ----------- code/c++/cxx-api/TrackPlatform_Manager.h | 4 ---- 7 files changed, 12 insertions(+), 18 deletions(-) diff --git a/code/c++/cxx-api/AutoConnector.cpp b/code/c++/cxx-api/AutoConnector.cpp index 17b8a0e..d7a9834 100644 --- a/code/c++/cxx-api/AutoConnector.cpp +++ b/code/c++/cxx-api/AutoConnector.cpp @@ -33,6 +33,7 @@ void AutoConnector::stop() { isRepeat.store(false); pConnectingThread->join(); delete pConnectingThread; + pConnectingThread = nullptr; } } diff --git a/code/c++/cxx-api/AutoConnector.h b/code/c++/cxx-api/AutoConnector.h index 5c0be5e..38038cd 100644 --- a/code/c++/cxx-api/AutoConnector.h +++ b/code/c++/cxx-api/AutoConnector.h @@ -18,7 +18,7 @@ class AutoConnector { uint32_t frequency; public: - AutoConnector(std::function c, uint32_t f = 500); + AutoConnector(std::function c, uint32_t f); ~AutoConnector(); void start(); void stop(); diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp index 50668e6..61a7880 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.cpp @@ -17,6 +17,7 @@ void TrackPlatform_BasicConnector::sendStartCommand() std::string command = std::string() + static_cast(communicationControllerID) + static_cast(startCommunicationCommand) + static_cast(APIWithAutoDiconnect); isConnectedToArduino = true; sendOneCommand(command); + autoConnector->start(); } void TrackPlatform_BasicConnector::sendStopCommand() { @@ -24,12 +25,17 @@ void TrackPlatform_BasicConnector::sendStopCommand() { throw NoConnectionException(); } + autoConnector->stop(); std::string command = std::string() + static_cast(communicationControllerID) + static_cast(stopCommunicationCommand); sendOneCommand(command); isConnectedToArduino = false; } -TrackPlatform_BasicConnector::TrackPlatform_BasicConnector() +TrackPlatform_BasicConnector::TrackPlatform_BasicConnector() : + autoConnector(new AutoConnector([this]() + { + this->sendOneCommand(std::string() + static_cast(communicationControllerID) + static_cast(refreshConnectionCommunicationCommand)); + }, timeoutToAutoreconnectInMs)) { } diff --git a/code/c++/cxx-api/TrackPlatform_BasicConnector.h b/code/c++/cxx-api/TrackPlatform_BasicConnector.h index 12370dd..d9f58cd 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicConnector.h +++ b/code/c++/cxx-api/TrackPlatform_BasicConnector.h @@ -2,15 +2,18 @@ #define _TRACKPLATFORM_BASICCONNECTOR_H_ #include +#include "AutoConnector.h" class TrackPlatform_BasicConnector { bool isConnectedToArduino = false; + AutoConnector* autoConnector = nullptr; protected: static const char stopSymbol = '|'; static const uint8_t timesToAutoreconnect = 3; static const uint32_t timeoutToNextConnectInMs = 500; + static const uint32_t timeoutToAutoreconnectInMs = 1000; static const std::string correctAnswer; virtual void write(const std::string& s) = 0; diff --git a/code/c++/cxx-api/TrackPlatform_BasicManagement.h b/code/c++/cxx-api/TrackPlatform_BasicManagement.h index 6e8d6a5..2e71897 100644 --- a/code/c++/cxx-api/TrackPlatform_BasicManagement.h +++ b/code/c++/cxx-api/TrackPlatform_BasicManagement.h @@ -14,7 +14,6 @@ class TrackPlatform_BasicManagement protected: static const uint8_t minSpeed = 0; static const uint8_t maxSpeed = 255; - static const uint32_t reconnectTime = 500; static const char delimiter = ';'; void sendMove(const std::string& additionalInfo); diff --git a/code/c++/cxx-api/TrackPlatform_Manager.cpp b/code/c++/cxx-api/TrackPlatform_Manager.cpp index ec3b710..4b512e2 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.cpp +++ b/code/c++/cxx-api/TrackPlatform_Manager.cpp @@ -27,24 +27,13 @@ TrackPlatform_BasicConnector* TrackPlatform_Manager::createConnectorByMode(Conne TrackPlatform_Manager::TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info) : TrackPlatform_BasicManagement(createConnectorByMode(mode, info)) { - std::function callback = [this]() { this->refreshConnection(); }; - pAutoConnector = new AutoConnector(callback, reconnectTime); - pAutoConnector->start(); } TrackPlatform_Manager::~TrackPlatform_Manager() { - if (pAutoConnector) delete pAutoConnector; TrackPlatform_BasicConnector* connector = getConnector(); if (connector) { delete connector; } } - -void TrackPlatform_Manager::startAutoConnection() { - pAutoConnector->start(); -} -void TrackPlatform_Manager::stopAutoConnection() { - pAutoConnector->stop(); -} \ No newline at end of file diff --git a/code/c++/cxx-api/TrackPlatform_Manager.h b/code/c++/cxx-api/TrackPlatform_Manager.h index 8cfae12..bc3f15c 100644 --- a/code/c++/cxx-api/TrackPlatform_Manager.h +++ b/code/c++/cxx-api/TrackPlatform_Manager.h @@ -9,14 +9,10 @@ class TrackPlatform_Manager : public TrackPlatform_BasicManagement { static TrackPlatform_BasicConnector* createConnectorByMode(ConnectionModes mode, const CommunicationInfoStruct& info); - AutoConnector* pAutoConnector = nullptr; public: TrackPlatform_Manager(ConnectionModes mode, const CommunicationInfoStruct& info); ~TrackPlatform_Manager(); - - void startAutoConnection(); - void stopAutoConnection(); }; #endif /* _TRACKPLATFORM_MANAGER_H_ */ From 4f4f9f48875259c7cad10ff7221769d7cfe99ea8 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 4 Sep 2017 23:01:38 +0300 Subject: [PATCH 116/336] Timer resetting was added after connecting new device (arduino-fw) --- code/Arduino/peripheral/ConnectionController.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/Arduino/peripheral/ConnectionController.cpp b/code/Arduino/peripheral/ConnectionController.cpp index 99b396d..d9ca3ee 100644 --- a/code/Arduino/peripheral/ConnectionController.cpp +++ b/code/Arduino/peripheral/ConnectionController.cpp @@ -144,6 +144,7 @@ String ConnectionController::getCommand() { isConnected = false; waitForConnection(); + timer.reset(); continue; } @@ -163,6 +164,7 @@ String ConnectionController::getCommand() { isConnected = false; waitForConnection(); + timer.reset(); continue; } From 3c11fdea209faa8c6b96bea3341328ff14de135e Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 5 Sep 2017 13:31:05 +0300 Subject: [PATCH 117/336] cxx-gamepad-app compilation fix on Windows --- code/c++/cxx-gamepad-app/SensorsViewer.cpp | 74 ------------------- code/c++/cxx-gamepad-app/SensorsViewer.h | 22 ------ code/c++/cxx-gamepad-app/cxx-gamepad-app.sln | 11 +++ .../cxx-gamepad-app/cxx-gamepad-app.vcxproj | 18 ++--- .../cxx-gamepad-app.vcxproj.filters | 6 -- 5 files changed, 19 insertions(+), 112 deletions(-) delete mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.cpp delete mode 100644 code/c++/cxx-gamepad-app/SensorsViewer.h diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.cpp b/code/c++/cxx-gamepad-app/SensorsViewer.cpp deleted file mode 100644 index 4e9ec81..0000000 --- a/code/c++/cxx-gamepad-app/SensorsViewer.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "SensorsViewer.h" - -void SensorsViewer::showDistanceInfo() -{ - if (!distanceSensors.empty()) { - //configuration - const short prefixSymbolNum = 1; - const short betweenSymbolNum = 1; - const short oneNumMinSize = 4; - const char delimiter = ' '; - std::ostream& os = std::cout; - - const short isParityOn = distanceSensors.size() % 2; - const short stringNums = distanceSensors.size() / 2; - os << "Distance sensors:" << std::endl; - const auto printChar = [](std::ostream& s, char c, short num) -> std::ostream& - { - while (num > 0) - { - s << c; - num--; - } - return s; - }; - if (isParityOn) - { - printChar(os, delimiter, prefixSymbolNum + stringNums + oneNumMinSize / 2) << - distanceSensors[stringNums] << std::endl; - } - for (short i = 0; i < stringNums; ++i) - { - printChar(os, delimiter, prefixSymbolNum + stringNums - i - 1) << - std::setw(oneNumMinSize) << distanceSensors[stringNums - i - 1]; - printChar(os, delimiter, i * 2 + betweenSymbolNum) << std::setw(oneNumMinSize) << - distanceSensors[stringNums + i + isParityOn - 1] << std::endl; - } - } -} - -void SensorsViewer::showLineInfo() -{ - if (!lineSensors.empty()) { - std::cout << "Line sensors:" << std::endl; - std::cout << "|"; - for (unsigned int i = 0; i < lineSensors.size(); i++) { - std::cout << (lineSensors[i] ? "@@@" : " "); - } - std::cout << "|" << std::endl; - } -} - -void SensorsViewer::setData(const std::vector& d, SensorType t) { - if (t == LINE_SENSORS) { - lineSensors = d; - } - else { - distanceSensors = d; - } -} - -void SensorsViewer::show() { - if (system("clear")) system("cls"); - showDistanceInfo(); - showLineInfo(); -} -void SensorsViewer::show(SensorType type) { - if (type == LINE_SENSORS) { - showLineInfo(); - } - else { - if (system("clear")) system("cls"); - showDistanceInfo(); - } -} \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/SensorsViewer.h b/code/c++/cxx-gamepad-app/SensorsViewer.h deleted file mode 100644 index c343f27..0000000 --- a/code/c++/cxx-gamepad-app/SensorsViewer.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include -#include -#include -#include - -enum SensorType { - LINE_SENSORS, DISTANCE_SENSORS -}; - -class SensorsViewer { - std::vector lineSensors; - std::vector distanceSensors; - - void showDistanceInfo(); - void showLineInfo(); - -public: - void setData(const std::vector& d, SensorType t); - void show(); - void show(SensorType type); -}; \ No newline at end of file diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln b/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln index e6a8e0d..357ea26 100644 --- a/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.sln @@ -5,6 +5,7 @@ VisualStudioVersion = 15.0.26430.16 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-gamepad-app", "cxx-gamepad-app.vcxproj", "{F92E7862-33C4-48B8-A055-3EE00352161F}" ProjectSection(ProjectDependencies) = postProject + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA} = {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA} {32D3778A-E59E-4DBC-8D86-BD23B708CA12} = {32D3778A-E59E-4DBC-8D86-BD23B708CA12} {4579D2EA-39EB-4766-9EB6-497500F379D6} = {4579D2EA-39EB-4766-9EB6-497500F379D6} EndProjectSection @@ -13,6 +14,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-api", "..\cxx-api\cxx-a EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libstem_gamepad", "gamepad_support\msvc\libstem_gamepad\libstem_gamepad.vcxproj", "{4579D2EA-39EB-4766-9EB6-497500F379D6}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxx-library", "..\cxx-library\cxx-library.vcxproj", "{57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -45,6 +48,14 @@ Global {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x64.Build.0 = Release|x64 {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x86.ActiveCfg = Release|Win32 {4579D2EA-39EB-4766-9EB6-497500F379D6}.Release|x86.Build.0 = Release|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x64.ActiveCfg = Debug|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x64.Build.0 = Debug|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x86.ActiveCfg = Debug|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Debug|x86.Build.0 = Debug|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x64.ActiveCfg = Release|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x64.Build.0 = Release|x64 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x86.ActiveCfg = Release|Win32 + {57E5EF7C-AF4E-45BA-A941-33A8C2D08DEA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj index e36df31..cb8c578 100644 --- a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj @@ -96,11 +96,11 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + $(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source Console - cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-library.lib;cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) $(OutDir);$(SolutionDir)$(Configuration)\ @@ -111,11 +111,11 @@ Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + $(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source Console - cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-library.lib;cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) $(OutDir);$(SolutionDir)$(Platform)\$(Configuration)\ @@ -128,13 +128,13 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + $(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source Console true true - cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-library.lib;cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) $(OutDir);$(SolutionDir)$(Configuration)\ @@ -147,13 +147,13 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source + $(SolutionDir)..\cxx-library;$(SolutionDir)..\cxx-api;$(SolutionDir)..\cxx-api\serial_support\include;$(SolutionDir)gamepad_support\source Console true true - cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + cxx-library.lib;cxx-api.lib;libstem_gamepad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) $(OutDir);$(SolutionDir)$(Platform)\$(Configuration)\ @@ -162,13 +162,11 @@ - - diff --git a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters index 9fc07e4..be33393 100644 --- a/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters +++ b/code/c++/cxx-gamepad-app/cxx-gamepad-app.vcxproj.filters @@ -27,9 +27,6 @@ Source Files - - Source Files - @@ -41,8 +38,5 @@ Header Files - - Header Files - \ No newline at end of file From 447bb5de22284d25d3d6e788190ac7b568f161f6 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Tue, 5 Sep 2017 21:32:20 +0300 Subject: [PATCH 118/336] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20cxx-gamepad-app=20=D0=BD=D0=B0=20linux:=20Sensor?= =?UTF-8?q?Viewer=20=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=83=D1=8E=20=D0=B1?= =?UTF-8?q?=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5=D0=BA=D1=83.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/c++/cxx-gamepad-app/makefile | 17 ++++++++++++++--- code/c++/cxx-library/SensorsViewer.cpp | 6 +++++- code/c++/cxx-library/SensorsViewer.h | 6 ++---- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/code/c++/cxx-gamepad-app/makefile b/code/c++/cxx-gamepad-app/makefile index da0a402..d2bfeea 100644 --- a/code/c++/cxx-gamepad-app/makefile +++ b/code/c++/cxx-gamepad-app/makefile @@ -63,16 +63,22 @@ OTHER_INCLUDE_PATH = $(OTHER_PATH) API_PATH = ../cxx-api API_INCLUDE_PATH = $(API_PATH) API_BUILD_PATH = $(API_PATH)/$(BUILD_PATH) +LIBRARY_PATH = ../cxx-library +LIBRARY_INCLUDE_PATH = $(LIBRARY_PATH) +LIBRARY_BUILD_PATH = $(LIBRARY_PATH)/$(BUILD_PATH) ifeq ($(BUILD), BUILD_STATIC) API_NAME = track-platform_cxx-api.a +LIBRARY_NAME = track-platform_cxx-library.a else ifeq ($(BUILD), BUILD_DYNAMIC) API_NAME = track-platform_cxx-api.so +LIBRARY_NAME = track-platform_cxx-library.so endif endif API_FULL_PATH = $(API_BUILD_PATH)/$(API_NAME) +LIBRARY_FULL_PATH = $(LIBRARY_BUILD_PATH)/$(LIBRARY_NAME) # gamepad library path GAMEPAD_LIB_PATH = gamepad_support @@ -96,6 +102,7 @@ SOURCES += $(OTHER_SOURCE_PATH)/main.cpp #Include file path INCLUDES = INCLUDES += -I$(API_INCLUDE_PATH) +INCLUDES += -I$(LIBRARY_INCLUDE_PATH) INCLUDES += -I$(GAMEPAD_LIB_INCLUDE_PATH) # INCLUDES += -I$(OTHER_INCLUDE_PATH) @@ -107,11 +114,11 @@ BIN = $(BUILD_PATH)/$(PROJECT_NAME) OBJECTS = $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(basename $(SOURCES)))) -STATIC_LIB: $(OBJECTS) api gamepad - @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) $(GAMEPAD_LIB_FULL_PATH) $(LFLAGS) +STATIC_LIB: $(OBJECTS) api library gamepad + @$(CXX) -o $(BIN) $(OBJECTS) $(API_FULL_PATH) $(LIBRARY_FULL_PATH) $(GAMEPAD_LIB_FULL_PATH) $(LFLAGS) @echo -e "$(BUILD_PRINT)" -DYNAMIC_LIB: $(OBJECTS) api gamepad +DYNAMIC_LIB: $(OBJECTS) api library gamepad $(error Dynamic library is not supported yet) # @$(CXX) -shared -o $(BIN) $(OBJECTS) @echo -e "$(BUILD_PRINT)" @@ -153,6 +160,9 @@ static: api: $(MAKE) -C $(API_PATH) BUILD=$(BUILD) +library: + $(MAKE) -C $(LIBRARY_PATH) BUILD=$(BUILD) + gamepad_include: $(MAKE) -C $(GAMEPAD_LIB_PATH) include @@ -164,6 +174,7 @@ preprocessor: gamepad_include clean: @rm -rf $(BUILD_PATH) $(MAKE) -C $(API_PATH) $@ + $(MAKE) -C $(LIBRARY_PATH) $@ $(MAKE) -C $(GAMEPAD_LIB_PATH) $@ run: diff --git a/code/c++/cxx-library/SensorsViewer.cpp b/code/c++/cxx-library/SensorsViewer.cpp index 4e9ec81..349e7ea 100644 --- a/code/c++/cxx-library/SensorsViewer.cpp +++ b/code/c++/cxx-library/SensorsViewer.cpp @@ -1,3 +1,7 @@ +#include +#include +#include + #include "SensorsViewer.h" void SensorsViewer::showDistanceInfo() @@ -71,4 +75,4 @@ void SensorsViewer::show(SensorType type) { if (system("clear")) system("cls"); showDistanceInfo(); } -} \ No newline at end of file +} diff --git a/code/c++/cxx-library/SensorsViewer.h b/code/c++/cxx-library/SensorsViewer.h index c343f27..3a8efcd 100644 --- a/code/c++/cxx-library/SensorsViewer.h +++ b/code/c++/cxx-library/SensorsViewer.h @@ -1,8 +1,6 @@ #pragma once -#include + #include -#include -#include enum SensorType { LINE_SENSORS, DISTANCE_SENSORS @@ -19,4 +17,4 @@ class SensorsViewer { void setData(const std::vector& d, SensorType t); void show(); void show(SensorType type); -}; \ No newline at end of file +}; From 654bebfd8d95349ba57b817956511782cb13a143 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Wed, 13 Sep 2017 15:59:31 +0300 Subject: [PATCH 119/336] =?UTF-8?q?=D0=9F=D0=BE=D1=87=D1=82=D0=B8=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=BD=D1=87=D0=B5=D0=BD=D0=B0=20=D0=BC=D0=BD?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D0=BA=D0=B0=D1=8F=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D0=B0=20Wi-Fi=20?= =?UTF-8?q?=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8F=20,=20=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BB=D0=BE=D1=81=D1=8C=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 96 +++++++++++++++++++++----------- code/Arduino/connectors/WiFi.h | 17 ++++++ 2 files changed, 79 insertions(+), 34 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index 1936e4b..574ecd2 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -62,6 +62,7 @@ bool WiFi::CheckOnAnswer() bool WiFi::Reset() { IDCount = -1; + IDList = ""; ready = false; opened = false; StartingSend("AT+RST"); @@ -134,15 +135,7 @@ String WiFi::ReturnInfo() String WiFi::CheckIPandMAC() { Send("AT+CIFSR"); - if (CheckOnAnswer()) - { - return ReturnInfo(); - } - else - { - Reset(); - return ""; - } + return ReturnInfo(); } bool WiFi::CreateCurrentHost(String name, String password, int port) @@ -274,7 +267,16 @@ void WiFi::send(String message) String WiFi::read() { - return Scan(); + if (messagecount >= 0) + { + String answer = MessageBox(messagecount); + messagecount--; + return answer; + } + else + { + return ""; + } } String WiFi::Read() @@ -286,11 +288,12 @@ String WiFi::Scan() { delay(100); String responce = Read(); - if (responce.indexOf(",CONNECT") == 1) + if (int x = (responce.indexOf(",CONNECT") >= 1) && responce.indexOf(",CONNECT") <= 3) { - String ID = responce.substring(0, 1); - if ((atoi(ID.c_str()) - 1) == IDCount) + String ID = responce.substring(0, x); + if (!(IDList.exist("." + ID + "."))) { + IDList + "." + ID + "."; IDCount++; return Scan(); } @@ -300,31 +303,40 @@ String WiFi::Scan() return ""; } } - if (responce.indexOf("/r/n+IPD,") == 0) + if (int y = (responce.indexOf(",CLOSED") >= 1) && responce.indexOf(",CLOSED") <= 3) { - String ID = responce.substring(7, 1); - String message = responce.substring(9, sizeof(responce) - 9); - String answer; - if (sizeof(message) < 11) + String ID = responce.substring(0, y); + if ((atoi(ID.c_str()) - 1) == IDCount) { - answer = message.substring(2, sizeof(message) - 2); - return answer; + IDlist = (IDList.substring(IDList.indexOf("." + ID + "."), (sizeof(ID) + 2)) + (IDList.substring((IDList.indexOf("." + ID + ".") + sizeof(ID) + 2), (IDList.substring((sizeof(IDList) - (IDList.indexOf("." + ID + ".") + (sizeof(ID) + 2))))))); + IDCount--; + return Scan(); } - if (sizeof(message) < 102) + else { - answer = message.substring(3, sizeof(message) - 3); - return answer; + Reset(); + return ""; } - if (sizeof(message) < 1003) + } + if (responce.indexOf("/r/n+IPD,") == 0) + { + responce = responce.substring(6, sizeof(responce) - 6); + int count = 1; + while (responce(count) != ",") { - answer = message.substring(4, sizeof(message) - 4); - return answer; + count++; } - if (sizeof(message) < 10004) + String ID = responce.substring(0, count - 1); + responce = responce.substring(count + 1, sizeof(responce) - count - 1); + count = 1; + while (responce(count) != ",") { - answer = message.substring(5, sizeof(message) - 5); - return answer; + count++; } + responce = responce.substring(count + 1, sizeof(responce) - count - 1); + messagecount++; + MessageBox(messagecount) = (ID + ": " + responce); + return Scan(); } else { @@ -334,10 +346,10 @@ String WiFi::Scan() String WiFi::CheckStatus() { - String response = ""; + String response; if (ready) { - response += "Ready"; + response = "Ready"; if (opened) { response += ", Opened, " + String(IDCount+1) + " Connected"; @@ -350,7 +362,7 @@ String WiFi::CheckStatus() } else { - response += "Fatal Error"; + response = "Fatal Error"; return response; } } @@ -363,9 +375,25 @@ bool WiFi::Write(int ID, String message) if (CheckOnAnswer()) { Send(message); - if (Scan() == ("busy s.../r/nRecv " + sizeof(message) + String(" bytes/r/nSEND OK"))) + if (Scan() == ("busy s...")) { - return true; + if (Scan() == ("/r/nRecv " + sizeof(message) + String(" bytes/r/nSEND OK"))) + { + if (Scan() == ("/r/nSEND OK")) + { + return true; + } + else + { + Reset(); + return false; + } + } + else + { + Reset(); + return false; + } } else { diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index a127056..7a4a118 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -130,7 +130,24 @@ class WiFi : public ConnectingDevice void send(String message) override; private: + /** + * @brief Почтовый ящик + */ + vector MessageBox; + + /** + * @brief Счётчик почтового ящика + */ + int messagecount = -1; + + /** + * @brief Список ID подключённых пользователей + */ + String IDList = ""; + /** + * @brief Число подключённых пользователей к модулю, уменьшенное на 1 + */ int IDCount = -1; /** From dc173dc49c96c44537992bff6859b572547d92ae Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Wed, 13 Sep 2017 22:42:21 +0300 Subject: [PATCH 120/336] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=B2=D0=BD=D1=83=D1=82=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D0=B8=D1=85=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 44 ++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index 574ecd2..e2cadad 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -21,9 +21,17 @@ WiFi::~WiFi() bool WiFi::CheckOnReady() { StartingSend("AT"); - if (ready != ((Scan() == "AT\r\nOK") == ReturningCommandsOff())) + if (ready != ((Scan() == "AT"))) { - return true; + if (ready != ((Scan() == "\r\nOK") == ReturningCommandsOff())) + { + return true; + } + else + { + Reset(); + return false; + } } else { @@ -35,9 +43,17 @@ bool WiFi::CheckOnReady() bool WiFi::ReturningCommandsOff() { StartingSend("ATE0"); - if (Scan() == "ATE0\r\nOK") + if (Scan() == "ATE0") { - return true; + if (Scan() == "\r\nOK") + { + return true; + } + else + { + Reset(); + return false; + } } else { @@ -66,9 +82,17 @@ bool WiFi::Reset() ready = false; opened = false; StartingSend("AT+RST"); - if (ready != ((Scan() == "AT+RST\r\nOK") == ReturningCommandsOff())) + if (ready != ((Scan() == "AT+RST"))) { - return ready = true; + if (ready != ((Scan() == "\r\nOK") == ReturningCommandsOff())) + { + return ready = true; + } + else + { + Reset(); + return false; + } } else { @@ -306,9 +330,9 @@ String WiFi::Scan() if (int y = (responce.indexOf(",CLOSED") >= 1) && responce.indexOf(",CLOSED") <= 3) { String ID = responce.substring(0, y); - if ((atoi(ID.c_str()) - 1) == IDCount) + if ((IDList.exist("." + ID + "."))) { - IDlist = (IDList.substring(IDList.indexOf("." + ID + "."), (sizeof(ID) + 2)) + (IDList.substring((IDList.indexOf("." + ID + ".") + sizeof(ID) + 2), (IDList.substring((sizeof(IDList) - (IDList.indexOf("." + ID + ".") + (sizeof(ID) + 2))))))); + IDlist = (IDList.substring(IDList.indexOf("." + ID + "."), (sizeof(ID) + 2)) + (IDList.substring((IDList.indexOf("." + ID + ".") + sizeof(ID) + 2), (IDList.substring((sizeof(IDList) - (IDList.indexOf("." + ID + ".") + (sizeof(ID) + 2)))))))); IDCount--; return Scan(); } @@ -352,7 +376,7 @@ String WiFi::CheckStatus() response = "Ready"; if (opened) { - response += ", Opened, " + String(IDCount+1) + " Connected"; + response += ", Opened, " + String(IDCount + 1) + " Connected, " + String(messagecount + 1) + " Incoming Messages"; } else { @@ -369,7 +393,7 @@ String WiFi::CheckStatus() bool WiFi::Write(int ID, String message) { - if (ID > -1 && ID <= IDCount) + if ((IDList.exist("." + String(ID) + "."))) { Send("AT+CIPSEND=" + String(ID) + sizeof(message)); if (CheckOnAnswer()) From 5295abee5abf0e4cf235fde668b9d32171f181e5 Mon Sep 17 00:00:00 2001 From: Fiery Bird Date: Wed, 13 Sep 2017 23:30:09 +0300 Subject: [PATCH 121/336] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=D0=BE=20=D0=BF=D0=BE=D0=B4=20Arduino=20Strin?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Arduino/connectors/WiFi.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index e2cadad..daed648 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -315,7 +315,7 @@ String WiFi::Scan() if (int x = (responce.indexOf(",CONNECT") >= 1) && responce.indexOf(",CONNECT") <= 3) { String ID = responce.substring(0, x); - if (!(IDList.exist("." + ID + "."))) + if (-1 == (IDList.indexOf("." + ID + "."))) { IDList + "." + ID + "."; IDCount++; @@ -330,9 +330,9 @@ String WiFi::Scan() if (int y = (responce.indexOf(",CLOSED") >= 1) && responce.indexOf(",CLOSED") <= 3) { String ID = responce.substring(0, y); - if ((IDList.exist("." + ID + "."))) + if (0 <= (IDList.indexOf("." + ID + "."))) { - IDlist = (IDList.substring(IDList.indexOf("." + ID + "."), (sizeof(ID) + 2)) + (IDList.substring((IDList.indexOf("." + ID + ".") + sizeof(ID) + 2), (IDList.substring((sizeof(IDList) - (IDList.indexOf("." + ID + ".") + (sizeof(ID) + 2)))))))); + IDList = (IDList.substring(IDList.indexOf("." + ID + "."), (sizeof(ID) + 2)) + (IDList.substring((IDList.indexOf("." + ID + ".") + sizeof(ID) + 2), (sizeof(IDList) - (IDList.indexOf("." + ID + ".") + (sizeof(ID) + 2)))))); IDCount--; return Scan(); } @@ -346,14 +346,14 @@ String WiFi::Scan() { responce = responce.substring(6, sizeof(responce) - 6); int count = 1; - while (responce(count) != ",") + while (responce[count] != ",") { count++; } String ID = responce.substring(0, count - 1); responce = responce.substring(count + 1, sizeof(responce) - count - 1); count = 1; - while (responce(count) != ",") + while (responce[count] != ",") { count++; } @@ -393,7 +393,7 @@ String WiFi::CheckStatus() bool WiFi::Write(int ID, String message) { - if ((IDList.exist("." + String(ID) + "."))) + if (0 <= (IDList.indexOf("." + String(ID) + "."))) { Send("AT+CIPSEND=" + String(ID) + sizeof(message)); if (CheckOnAnswer()) From ab879b94b6e54ebae9a847a57b80d00822a0da89 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 13 Sep 2017 23:45:17 +0300 Subject: [PATCH 122/336] Vector prototype was written and Wi-fi usage was fixed --- code/Arduino/connectors/WiFi.cpp | 4 +- code/Arduino/connectors/WiFi.h | 3 +- code/Arduino/trackPlatform.vcxproj.filters | 3 ++ code/Arduino/utils/Vector.h | 51 ++++++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 code/Arduino/utils/Vector.h diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index e2cadad..ad4e80f 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -293,7 +293,7 @@ String WiFi::read() { if (messagecount >= 0) { - String answer = MessageBox(messagecount); + String answer = MessageBox.pop(); messagecount--; return answer; } @@ -359,7 +359,7 @@ String WiFi::Scan() } responce = responce.substring(count + 1, sizeof(responce) - count - 1); messagecount++; - MessageBox(messagecount) = (ID + ": " + responce); + MessageBox.push(ID + ": " + responce); return Scan(); } else diff --git a/code/Arduino/connectors/WiFi.h b/code/Arduino/connectors/WiFi.h index 7a4a118..a069060 100644 --- a/code/Arduino/connectors/WiFi.h +++ b/code/Arduino/connectors/WiFi.h @@ -1,4 +1,5 @@ #pragma once +#include "../utils/Vector.h" #include "ConnectingDevice.h" class WiFi : public ConnectingDevice @@ -133,7 +134,7 @@ class WiFi : public ConnectingDevice /** * @brief Почтовый ящик */ - vector MessageBox; + Vector MessageBox; /** * @brief Счётчик почтового ящика diff --git a/code/Arduino/trackPlatform.vcxproj.filters b/code/Arduino/trackPlatform.vcxproj.filters index b43e0c7..210a8a9 100644 --- a/code/Arduino/trackPlatform.vcxproj.filters +++ b/code/Arduino/trackPlatform.vcxproj.filters @@ -102,6 +102,9 @@ peripheral\header + + utils\header + diff --git a/code/Arduino/utils/Vector.h b/code/Arduino/utils/Vector.h new file mode 100644 index 0000000..981af49 --- /dev/null +++ b/code/Arduino/utils/Vector.h @@ -0,0 +1,51 @@ +#pragma once + +template +class Vector +{ + template + struct Node + { + T1 obj; + Node* next = nullptr; + }; + + Node* begin = nullptr; + Node* end = nullptr; +public: + ~Vector(); + + void push(const T& t); + T pop(); + + bool isEmpty() const; +}; + +template +Vector::~Vector() +{ + while (!isEmpty()) + { + pop(); + } +} + +template +void Vector::push(const T& t) +{ + //TODO +} + +template +T Vector::pop() +{ + //TODO + return T(); +} + +template +bool Vector::isEmpty() const +{ + //TODO + return false; +} From e1d833dce867975f0bb8c96669a09c14eee407ee Mon Sep 17 00:00:00 2001 From: AJIOB Date: Thu, 14 Sep 2017 00:05:16 +0300 Subject: [PATCH 123/336] Vector push(), pop(), isEmpty() methods were written --- code/Arduino/trackPlatform.vcxproj | 1 + code/Arduino/utils/Vector.h | 49 +++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/code/Arduino/trackPlatform.vcxproj b/code/Arduino/trackPlatform.vcxproj index 4ec9ad7..62ac2ab 100644 --- a/code/Arduino/trackPlatform.vcxproj +++ b/code/Arduino/trackPlatform.vcxproj @@ -100,6 +100,7 @@ + diff --git a/code/Arduino/utils/Vector.h b/code/Arduino/utils/Vector.h index 981af49..13dfe06 100644 --- a/code/Arduino/utils/Vector.h +++ b/code/Arduino/utils/Vector.h @@ -1,4 +1,5 @@ #pragma once +#include "../connectors/DebugSerial.h" template class Vector @@ -33,19 +34,57 @@ Vector::~Vector() template void Vector::push(const T& t) { - //TODO + // creating new block + Node * newEnd = new Node; + if (!newEnd) + { + DEBUG_PRINTLN("Cannot allocate memory for new vector element"); + return; + } + + newEnd->obj = t; + + // linking new block + if (begin == nullptr) + { + begin = end = newEnd; + } + else + { + end->next = newEnd; + end = newEnd; + } } template T Vector::pop() { - //TODO - return T(); + if (isEmpty()) + { + return T(); + } + + // save pop result + T result = begin->obj; + + // move begin pointer + Node* oldBegin = begin; + begin = begin->next; + + // null end pointer if require + if (oldBegin == end) + { + end = nullptr; + } + + // clear old memory + delete oldBegin; + + return result; } template bool Vector::isEmpty() const { - //TODO - return false; + return !begin; } From e018333a5fe1cf2421e938c6570511b3377c7153 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 23 Sep 2017 23:58:13 +0300 Subject: [PATCH 124/336] Compilation warnings fix (comparing char and char[]) --- code/Arduino/connectors/WiFi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Arduino/connectors/WiFi.cpp b/code/Arduino/connectors/WiFi.cpp index f391a50..62f6411 100644 --- a/code/Arduino/connectors/WiFi.cpp +++ b/code/Arduino/connectors/WiFi.cpp @@ -346,14 +346,14 @@ String WiFi::Scan() { responce = responce.substring(6, sizeof(responce) - 6); int count = 1; - while (responce[count] != ",") + while (responce[count] != ',') { count++; } String ID = responce.substring(0, count - 1); responce = responce.substring(count + 1, sizeof(responce) - count - 1); count = 1; - while (responce[count] != ",") + while (responce[count] != ',') { count++; } From efdf974af110f41fc2ad74479a24b1e0820a1e68 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 24 Sep 2017 23:20:35 +0300 Subject: [PATCH 125/336] Requirements basic template was import --- docs/Requirements.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/Requirements.md diff --git a/docs/Requirements.md b/docs/Requirements.md new file mode 100644 index 0000000..5886863 --- /dev/null +++ b/docs/Requirements.md @@ -0,0 +1,22 @@ +# Требования к проекту +1) Введение +Во введении описывается контекст проекта. Определить название продукта. В общих чертах описать, что продукт будет делать и чего он делать не будет (определить границы проекта) +2) Требования пользователя +2.1) Программные интерфейсы +Перечислить внешние системы / библиотеки / сервисы, с которыми продукт будет взаимодйствовать. +2.2) Интерфейс пользователя +Описать, как система будет взаимодействовать с пользователем. Возможны следующие варианты описания: +текстовое +иллюстрации (мокапы) +таблицы “действие пользователя - реакция” +2.3) Характеристики пользователей +Идентифицировать пользователей (группы пользователей) и описать их характеристики (включая уровень образования, опыт, техническую грамотность) +2.4) Предположения и зависимости +Перечислить факторы, которые могут повлиять на требования к системе, описанные в данном документе. +3) Системные требования +Этот раздел должен содержать требования к продукту описанные на уровне достаточном для однозначного понимания того, как система может быть спроектирована и протестирована на предмет удовлетворения данных требований. +3.1) Функциональные требования +Можно представить в виде нумерованного списка (для однозначной идентификации требований) +3.2) Нефункциональные требования +3.2.1) АТРИБУТЫ КАЧЕСТВА +Перечислить атрибуты качества, важные для данной системы (надёжность, безопасность и т.д.) и пояснить почему они важны и как они должны измеряться. \ No newline at end of file From 48f0fbd2b483688a05b923d5d576a223d651ba22 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 24 Sep 2017 23:42:33 +0300 Subject: [PATCH 126/336] Table of contents was added --- docs/Requirements.md | 70 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 5886863..3cce0cf 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -1,22 +1,66 @@ # Требования к проекту -1) Введение +--- + +# Содержание +1) [Введение](#intro) +2) [Требования пользователя](#user_requires) +2.1) [Программные интерфейсы](#program_interfaces) +2.2) [Интерфейс пользователя](#user_interface) +2.3) [Характеристики пользователей](#user_description) +2.4) [Предположения и зависимости](#dependencies) +3) [Системные требования](#system_requires) +3.1) [Функциональные требования](#functional_requires) +3.2) [Нефункциональные требования](#nonfunctional_requires) +3.2.1) [Атрибуты качаства](#quality_attributes) + + + +# Введение + Во введении описывается контекст проекта. Определить название продукта. В общих чертах описать, что продукт будет делать и чего он делать не будет (определить границы проекта) -2) Требования пользователя -2.1) Программные интерфейсы + + + +# Требования пользователя + + + +## Программные интерфейсы Перечислить внешние системы / библиотеки / сервисы, с которыми продукт будет взаимодйствовать. -2.2) Интерфейс пользователя + + + +## Интерфейс пользователя Описать, как система будет взаимодействовать с пользователем. Возможны следующие варианты описания: -текстовое -иллюстрации (мокапы) -таблицы “действие пользователя - реакция” -2.3) Характеристики пользователей +- текстовое +- иллюстрации (мокапы) +- таблицы “действие пользователя - реакция” + + + +## Характеристики пользователей Идентифицировать пользователей (группы пользователей) и описать их характеристики (включая уровень образования, опыт, техническую грамотность) -2.4) Предположения и зависимости + + + +## Предположения и зависимости Перечислить факторы, которые могут повлиять на требования к системе, описанные в данном документе. -3) Системные требования + + + +# Системные требования Этот раздел должен содержать требования к продукту описанные на уровне достаточном для однозначного понимания того, как система может быть спроектирована и протестирована на предмет удовлетворения данных требований. -3.1) Функциональные требования + + + +## Функциональные требования Можно представить в виде нумерованного списка (для однозначной идентификации требований) -3.2) Нефункциональные требования -3.2.1) АТРИБУТЫ КАЧЕСТВА + + + +## Нефункциональные требования + + + +### Атрибуты качества Перечислить атрибуты качества, важные для данной системы (надёжность, безопасность и т.д.) и пояснить почему они важны и как они должны измеряться. \ No newline at end of file From f995c6a3b98a1d9c4a4a5fba159c2ebebf8347b0 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 24 Sep 2017 23:57:53 +0300 Subject: [PATCH 127/336] Introduction was written --- docs/Requirements.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 3cce0cf..293f0f5 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -3,21 +3,28 @@ # Содержание 1) [Введение](#intro) -2) [Требования пользователя](#user_requires) -2.1) [Программные интерфейсы](#program_interfaces) -2.2) [Интерфейс пользователя](#user_interface) -2.3) [Характеристики пользователей](#user_description) -2.4) [Предположения и зависимости](#dependencies) +2) [Требования пользователя](#user_requires) +2.1) [Программные интерфейсы](#program_interfaces) +2.2) [Интерфейс пользователя](#user_interface) +2.3) [Характеристики пользователей](#user_description) +2.4) [Предположения и зависимости](#dependencies) 3) [Системные требования](#system_requires) -3.1) [Функциональные требования](#functional_requires) -3.2) [Нефункциональные требования](#nonfunctional_requires) -3.2.1) [Атрибуты качаства](#quality_attributes) +3.1) [Функциональные требования](#functional_requires) +3.2) [Нефункциональные требования](#nonfunctional_requires) +3.2.1) [Атрибуты качаства](#quality_attributes) # Введение -Во введении описывается контекст проекта. Определить название продукта. В общих чертах описать, что продукт будет делать и чего он делать не будет (определить границы проекта) + +Данный проект предназначен для помощи студентам и разработчикам, работающим с программным +обеспечением (далее - ПО), которое не связано программированием микроконтроллеров, +использовать микроконтроллеры +и их возможности для выполнения поставленных задач. Цель данного проекта - написать программное +обеспечение для микроконтроллера (далее - прошивку) и предоставить программисту интерфейсы для +взаимодействия с hardware-уровнем (уровнем микроконтроллеров) и использованием его возможностей с +помощью отправки команд микроконтроллеру. From 9329c2fe1dbfa7ff91921dcc1b452c1358952d05 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 25 Sep 2017 00:23:04 +0300 Subject: [PATCH 128/336] Programming interfaces was written. Name and requrements were added to introduction --- docs/Requirements.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 293f0f5..a869273 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -2,13 +2,13 @@ --- # Содержание -1) [Введение](#intro) +1) [Введение](#intro) 2) [Требования пользователя](#user_requires) 2.1) [Программные интерфейсы](#program_interfaces) 2.2) [Интерфейс пользователя](#user_interface) 2.3) [Характеристики пользователей](#user_description) 2.4) [Предположения и зависимости](#dependencies) -3) [Системные требования](#system_requires) +3) [Системные требования](#system_requires) 3.1) [Функциональные требования](#functional_requires) 3.2) [Нефункциональные требования](#nonfunctional_requires) 3.2.1) [Атрибуты качаства](#quality_attributes) @@ -18,6 +18,8 @@ # Введение +Название проекта: trackPlatform. +Вид проекта: аппаратно-программная платформа (далее - аппаратная платформа, платформа). Данный проект предназначен для помощи студентам и разработчикам, работающим с программным обеспечением (далее - ПО), которое не связано программированием микроконтроллеров, использовать микроконтроллеры @@ -25,6 +27,12 @@ обеспечение для микроконтроллера (далее - прошивку) и предоставить программисту интерфейсы для взаимодействия с hardware-уровнем (уровнем микроконтроллеров) и использованием его возможностей с помощью отправки команд микроконтроллеру. +Сама аппаратная платформа должна уметь: +- передавать информацию с датчиков расстояния и линии в режиме реального времени; +- перемещаться в пространстве в двух плоскостях, используя гусеницы (т.е. устройство + не должно уметь летать); +- управлять поворотной платформой, установленной на корпусе (вращение относительно двух осей; +- принимать команды для их последующей обработки и ответа на них, если требуется. @@ -33,7 +41,19 @@ ## Программные интерфейсы -Перечислить внешние системы / библиотеки / сервисы, с которыми продукт будет взаимодйствовать. + +Данное устройство должно взаимодействовать только с API (библиоткеой для взаимодействия +с данной аппаратной платформой), написанных на разных языках +программирования, используя свою прошивку. Сами API могут быть использованы в различных +приложениях, например: +- управление платформой с помощью смартфона; +- системы исследования местности. + +Взаимодействие с API должно проводиться как с использованием проводных (через USB-кабель), + так и беспроводных (через Bluetooth) систем связи. API может быть реализовано самим + разработчиком, так и сторонними. Обе стороны (API и платформа) обязаны безукоризеннно + следовать протоколу. + From 58afb317a648aa6d323ca85a5e8379100b6c2d88 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 25 Sep 2017 15:01:17 +0300 Subject: [PATCH 129/336] Protocol and supported commands prototypes were added --- docs/Requirements.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index a869273..9e6f89e 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -5,6 +5,8 @@ 1) [Введение](#intro) 2) [Требования пользователя](#user_requires) 2.1) [Программные интерфейсы](#program_interfaces) +2.1.1) [Протокол взаимодействия](#protocol) +2.1.2) [Список поддерживаемых команд](#supported_commands) 2.2) [Интерфейс пользователя](#user_interface) 2.3) [Характеристики пользователей](#user_description) 2.4) [Предположения и зависимости](#dependencies) @@ -52,8 +54,18 @@ Взаимодействие с API должно проводиться как с использованием проводных (через USB-кабель), так и беспроводных (через Bluetooth) систем связи. API может быть реализовано самим разработчиком, так и сторонними. Обе стороны (API и платформа) обязаны безукоризеннно - следовать протоколу. + следовать [протоколу](#protocol). + + +### Протокол взаимодействия +Для взаимодействия с платформой требуется реализовать следующий протокол: +TODO + + + +### Список поддерживаемых команд +TODO From d27462d74773035459d693ec561711b69c4696c3 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 26 Sep 2017 16:37:29 +0300 Subject: [PATCH 130/336] Main protocol was added --- docs/Requirements.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 9e6f89e..3027b64 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -59,7 +59,16 @@ ### Протокол взаимодействия -Для взаимодействия с платформой требуется реализовать следующий протокол: +Для взаимодействия с платформой требуется реализовать протокол, который будет принимать команды и отвечать на них. +Формат любой посылки (на прием или передачу): +*<размер данных> <данные> <контрольная сумма>* + +| Элемент команды | Размер | Описание | +|:---|:---|:---| +| Размер данных | 1 байт | Размер данных в байтах (пересылается в двоичном виде) | +| Данные | До 255 байт включительно (ограничено возможностями поля "Размер данных") | Пересылаемые данные | +| Контрольная сумма | 2 байта | Контрольная сумма, рассчитанная по алгоритму CRC-16 IBM (полином версии 0x8005) | + TODO From 0b1c2c364b3b7d9a570d382da3b9798f892c3971 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 26 Sep 2017 18:09:28 +0300 Subject: [PATCH 131/336] Data format was added. Answer types were added. --- docs/Requirements.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 3027b64..b1f1199 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -69,7 +69,25 @@ | Данные | До 255 байт включительно (ограничено возможностями поля "Размер данных") | Пересылаемые данные | | Контрольная сумма | 2 байта | Контрольная сумма, рассчитанная по алгоритму CRC-16 IBM (полином версии 0x8005) | -TODO +Формат данных команды (отправляется из приложения через API на устройство): +*<контроллер> <команда контролера> <параметры команды (если требуется командой)>* + +| Элемент команды | Описание | +|:---|:---| +| Контроллер | выбор контроллера (контроллер движения, датчиков, сервопривода или связи) | +| Команда контроллера | команда контроллеру (например: движение вперед) | +| Параметры команды | необязательный параметр, обычно одно или несколько чисел в виде строки (а не в двоичном виде), разделяемые символом-разделителем и которые прилагаются к команде | + +Формат данных ответа полностью зависит от команды, на которую платформа будет отправлять ответ. +Ответы также могут быть управляющими (синхронизирующими). Существует два вида управляющих ответов: +- OK +- ERROR + +Первый - утвердительный, второй - отрицательный. +При полном приеме команды от приложения будет сформирован ответ: +утвердительный - при принятии команды без повреждений, отрицательный - в случаях +повреждения посылки либо принятии команды с несоответствующим форматом. +При посылке отрицательного ответа на команду платформа переходит в режим ожидания команды. From b1b04f6492fbcc7c3b9cfbec76d15090b5f9ffee Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 3 Oct 2017 11:11:38 +0300 Subject: [PATCH 132/336] Dependencies and functional requirements were added --- docs/Requirements.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index b1f1199..cc41ad7 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -110,7 +110,12 @@ TODO ## Предположения и зависимости -Перечислить факторы, которые могут повлиять на требования к системе, описанные в данном документе. + +На требования к данной платформе и протоколу для взаимодействия с ней могут повлиять: + +- добавление новых интерфейсов связи или данных (например, Wi-Fi, SD карты); +- изменение требований к ПО; +- добавление других видов датчиков для платформы (например, компаса); @@ -120,7 +125,13 @@ TODO ## Функциональные требования -Можно представить в виде нумерованного списка (для однозначной идентификации требований) + +1. поддержка проводного интерфейса связи (соединение по USB); +1. поддержка беспроводного интерфейса связи (соединение по Bluetooth); +1. управление гусеничной платформой; +1. управление поворотной платформой (сервоприводами); +1. получение информации с датчиков линии; +1. получение информации с датчиков расстояния; From 911ecbe273e356f26feac0b197248be863b3425d Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 3 Oct 2017 22:01:33 +0300 Subject: [PATCH 133/336] User description was added --- docs/Requirements.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index cc41ad7..745c467 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -105,7 +105,11 @@ TODO ## Характеристики пользователей -Идентифицировать пользователей (группы пользователей) и описать их характеристики (включая уровень образования, опыт, техническую грамотность) + +Данное решение предназначено для студентов технических специальностей (будущих разработчиков ПО) + и разработчиков, которые знакомы с последовательными протоколами передачи данных + (например, RS-232) и их видами и которые понимают как они функционируют. + From 34c64ea2baf5935872eacd94010b52251f2fcd15 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 3 Oct 2017 22:22:37 +0300 Subject: [PATCH 134/336] Analogues were added --- docs/Requirements.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 745c467..86aa5ce 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -3,6 +3,7 @@ # Содержание 1) [Введение](#intro) +2) [Аналоги](#analogues) 2) [Требования пользователя](#user_requires) 2.1) [Программные интерфейсы](#program_interfaces) 2.1.1) [Протокол взаимодействия](#protocol) @@ -36,6 +37,15 @@ - управлять поворотной платформой, установленной на корпусе (вращение относительно двух осей; - принимать команды для их последующей обработки и ответа на них, если требуется. + + +# Аналоги + +Данный проект имеет аналог: свою предыдущую версию. Предыдущая версия проекта не имеет +четкой структуры и для добавления новых функций в систему требуется переписывать +большое количество имеющегося кода. Требуется по возможности устранить данные недостатки +системы. + # Требования пользователя @@ -44,7 +54,7 @@ ## Программные интерфейсы -Данное устройство должно взаимодействовать только с API (библиоткеой для взаимодействия +Данное устройство должно взаимодействовать только с API (библиотекой для взаимодействия с данной аппаратной платформой), написанных на разных языках программирования, используя свою прошивку. Сами API могут быть использованы в различных приложениях, например: From e9e08cf664a4186311195cedaccc3778d477c249 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 3 Oct 2017 22:26:30 +0300 Subject: [PATCH 135/336] Table of content was fixed. Some functional requirements were updated --- docs/Requirements.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 86aa5ce..801e28c 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -5,16 +5,16 @@ 1) [Введение](#intro) 2) [Аналоги](#analogues) 2) [Требования пользователя](#user_requires) -2.1) [Программные интерфейсы](#program_interfaces) -2.1.1) [Протокол взаимодействия](#protocol) -2.1.2) [Список поддерживаемых команд](#supported_commands) -2.2) [Интерфейс пользователя](#user_interface) -2.3) [Характеристики пользователей](#user_description) -2.4) [Предположения и зависимости](#dependencies) + 1) [Программные интерфейсы](#program_interfaces) + 1) [Протокол взаимодействия](#protocol) + 1) [Список поддерживаемых команд](#supported_commands) + 2) [Интерфейс пользователя](#user_interface) + 3) [Характеристики пользователей](#user_description) + 4) [Предположения и зависимости](#dependencies) 3) [Системные требования](#system_requires) -3.1) [Функциональные требования](#functional_requires) -3.2) [Нефункциональные требования](#nonfunctional_requires) -3.2.1) [Атрибуты качаства](#quality_attributes) + 1) [Функциональные требования](#functional_requires) + 2) [Нефункциональные требования](#nonfunctional_requires) + 1) [Атрибуты качаства](#quality_attributes) @@ -134,7 +134,7 @@ TODO # Системные требования -Этот раздел должен содержать требования к продукту описанные на уровне достаточном для однозначного понимания того, как система может быть спроектирована и протестирована на предмет удовлетворения данных требований. + @@ -144,8 +144,10 @@ TODO 1. поддержка беспроводного интерфейса связи (соединение по Bluetooth); 1. управление гусеничной платформой; 1. управление поворотной платформой (сервоприводами); -1. получение информации с датчиков линии; -1. получение информации с датчиков расстояния; +1. получение корректной информации с датчиков линии (с "заводской" калибровкой датчиков +в виде констант); +1. получение информации с датчиков расстояния (с "заводской" калибровкой датчиков +в виде констант); From 0f51114fbfc9600e1091cbf743fe853d69637880 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 3 Oct 2017 23:22:03 +0300 Subject: [PATCH 136/336] Some updates --- docs/Requirements.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 801e28c..fa62fac 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -34,7 +34,7 @@ - передавать информацию с датчиков расстояния и линии в режиме реального времени; - перемещаться в пространстве в двух плоскостях, используя гусеницы (т.е. устройство не должно уметь летать); -- управлять поворотной платформой, установленной на корпусе (вращение относительно двух осей; +- управлять поворотной платформой, установленной на корпусе (вращение относительно двух осей); - принимать команды для их последующей обработки и ответа на них, если требуется. @@ -45,6 +45,7 @@ четкой структуры и для добавления новых функций в систему требуется переписывать большое количество имеющегося кода. Требуется по возможности устранить данные недостатки системы. +Также в данной реализации требуется убрать поддержку редко используемых команд. @@ -104,13 +105,13 @@ ### Список поддерживаемых команд TODO - + @@ -148,6 +149,7 @@ TODO в виде констант); 1. получение информации с датчиков расстояния (с "заводской" калибровкой датчиков в виде констант); +1. убрать поддержку редко используемых команд (неописанные старые команды); @@ -156,4 +158,4 @@ TODO ### Атрибуты качества -Перечислить атрибуты качества, важные для данной системы (надёжность, безопасность и т.д.) и пояснить почему они важны и как они должны измеряться. \ No newline at end of file + From 34996399cb93f6aca62106828ab6512eb274ccc0 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 3 Oct 2017 23:27:05 +0300 Subject: [PATCH 137/336] Protocol communication updates --- docs/Requirements.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Requirements.md b/docs/Requirements.md index fa62fac..ce16951 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -99,6 +99,8 @@ утвердительный - при принятии команды без повреждений, отрицательный - в случаях повреждения посылки либо принятии команды с несоответствующим форматом. При посылке отрицательного ответа на команду платформа переходит в режим ожидания команды. +Также по завершению выполнения команды будет возвращен один из управляющих ответов. +Только после этого настоятельно рекомендуется посылать следующую команду. From c29d5566c96c89b6a06cf32367b407a0336eb6c3 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 4 Oct 2017 09:24:56 +0300 Subject: [PATCH 138/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=20=D1=82?= =?UTF-8?q?=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/requirement.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 documentation/requirement.md diff --git a/documentation/requirement.md b/documentation/requirement.md new file mode 100644 index 0000000..7cd6716 --- /dev/null +++ b/documentation/requirement.md @@ -0,0 +1,11 @@ +# Требования к проекту + +1. Введение +2. Требования пользователя + 2.1. Программные интерфейсы + 2.2. Интерфес пользователя + 2.3. Характреристики пользователей + 2.4. Предположения и зависимости +3. Системные требования + 3.1. Функциональные требования + 3.2. Нефункциональныые требования From d269b12185d99084a7de74a4f82158f4bdc76e96 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 4 Oct 2017 09:31:59 +0300 Subject: [PATCH 139/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5?= =?UTF-8?q?=D0=BC=D0=B0=20=D1=81=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20=D1=81=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=BA=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/requirement.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/requirement.md b/documentation/requirement.md index 7cd6716..4686cbd 100644 --- a/documentation/requirement.md +++ b/documentation/requirement.md @@ -2,10 +2,10 @@ 1. Введение 2. Требования пользователя - 2.1. Программные интерфейсы - 2.2. Интерфес пользователя - 2.3. Характреристики пользователей - 2.4. Предположения и зависимости + 1. Программные интерфейсы + 2. Интерфес пользователя + 3. Характреристики пользователей + 4. Предположения и зависимости 3. Системные требования - 3.1. Функциональные требования - 3.2. Нефункциональныые требования + 1. Функциональные требования + 2. Нефункциональныые требования From e193bd1c6c5793825acbe6639892c342d320ba08 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 4 Oct 2017 10:13:12 +0300 Subject: [PATCH 140/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=B2=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/requirement.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/documentation/requirement.md b/documentation/requirement.md index 4686cbd..7c19301 100644 --- a/documentation/requirement.md +++ b/documentation/requirement.md @@ -9,3 +9,27 @@ 3. Системные требования 1. Функциональные требования 2. Нефункциональныые требования + +#Введение + +Название проекта: Android приложение для аппаратной платформы trackPlatform. +Вид проекта: программное обеспечение. +Назначение данного проекта - это создание приложения для управления аппаратной платформой trackPlatform. + +#Требования пользователя +##Прогрмааные интерфейсы +Приложение должно взаимодействовать с прошивкой аппаратной платформы по приведенному ниже протоколу. +Взаимодействие с прошивкой будет осуществлятся оп беспроводной связи(через Bluetooth). + +##Интерфес пользователя + +##Характреристики пользователей +Данное приложение предназначено для пользователей имеющих базовые знания операционной системы Android. +Пользователь должен уметь включать и отключать Bluetooth на своем устройстве, а также уметь подключиться +к определенному устройству через Bluetooth. Также пользователю необходимо иметь доступ к самой аппаратной +платформе. + +##Предположения и зависимости + + + From 51ecfc7c2dba0a026debfd179e3426be35a666ba Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 4 Oct 2017 10:24:52 +0300 Subject: [PATCH 141/336] Update requirement.md --- documentation/requirement.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/documentation/requirement.md b/documentation/requirement.md index 7c19301..5172e4e 100644 --- a/documentation/requirement.md +++ b/documentation/requirement.md @@ -10,26 +10,26 @@ 1. Функциональные требования 2. Нефункциональныые требования -#Введение +## Введение Название проекта: Android приложение для аппаратной платформы trackPlatform. Вид проекта: программное обеспечение. Назначение данного проекта - это создание приложения для управления аппаратной платформой trackPlatform. -#Требования пользователя -##Прогрмааные интерфейсы +## Требования пользователя +### Прогрмааные интерфейсы Приложение должно взаимодействовать с прошивкой аппаратной платформы по приведенному ниже протоколу. -Взаимодействие с прошивкой будет осуществлятся оп беспроводной связи(через Bluetooth). +Взаимодействие с прошивкой будет осуществлятся по беспроводной связи(через Bluetooth). -##Интерфес пользователя +### Интерфес пользователя -##Характреристики пользователей +### Характреристики пользователей Данное приложение предназначено для пользователей имеющих базовые знания операционной системы Android. Пользователь должен уметь включать и отключать Bluetooth на своем устройстве, а также уметь подключиться к определенному устройству через Bluetooth. Также пользователю необходимо иметь доступ к самой аппаратной платформе. -##Предположения и зависимости +### Предположения и зависимости From 98c6dd14a00fba26137e6f9304eeca757ce16b9e Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 4 Oct 2017 13:57:49 +0300 Subject: [PATCH 142/336] Move and servo commands were added. One functional requirement was added. --- docs/Requirements.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/Requirements.md b/docs/Requirements.md index ce16951..8541357 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -107,6 +107,28 @@ ### Список поддерживаемых команд TODO +Ниже приведен список контроллеров с их HEX-идентификаторами (в скобках) и их поддерживаемые команды: +- Гусеницы (01) + +| Команда (ее HEX-идентификатор) | Параметры | +|:---|:---| +| Установка скорости какой-то конкретной гусеницы (09) | 1. Номер гусеницы в промежутке [-255, 255] | +| Движение вперед (06) | 1. Скорость движения в промежутке [-255, 255] | +| Поворот по часовой стрелке (0A) | 1. Скорость поворота в промежутке [-255, 255] | +| Полная остановка (05) | - | + +- Сервоприводы (03) + +| Команда (ее HEX-идентификатор) | Параметры | +|:---|:---| +| Установить угол для определенной оси (05) | 1. Идентификатор оси (номер); 2. Угол отклонения от от левого крайнего положения в градусах (промежуток [0, 180]) | +| Получить текущий угол отклонения от левого края (06) | 1. Идентификатор оси (номер); | + +| Плоскость | Идентификатор | +|:---|:---| +| xy | 1 | +| xz | 2 | + + + + diff --git a/code/Java/Mobile/Application2.0/app/src/test/java/com/example/kimentii/application20/ExampleUnitTest.java b/code/Java/Mobile/Application2.0/app/src/test/java/com/example/kimentii/application20/ExampleUnitTest.java new file mode 100644 index 0000000..dd78452 --- /dev/null +++ b/code/Java/Mobile/Application2.0/app/src/test/java/com/example/kimentii/application20/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.example.kimentii.application20; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/code/Java/Mobile/Application2.0/build.gradle b/code/Java/Mobile/Application2.0/build.gradle new file mode 100644 index 0000000..c2eea8e --- /dev/null +++ b/code/Java/Mobile/Application2.0/build.gradle @@ -0,0 +1,23 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.3' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/code/Java/Mobile/Application2.0/gradle.properties b/code/Java/Mobile/Application2.0/gradle.properties new file mode 100644 index 0000000..aac7c9b --- /dev/null +++ b/code/Java/Mobile/Application2.0/gradle.properties @@ -0,0 +1,17 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/code/Java/Mobile/Application2.0/gradle/wrapper/gradle-wrapper.jar b/code/Java/Mobile/Application2.0/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..13372aef5e24af05341d49695ee84e5f9b594659 GIT binary patch literal 53636 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ⅅ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 H-+%o-(+5aQ literal 0 HcmV?d00001 diff --git a/code/Java/Mobile/Application2.0/gradle/wrapper/gradle-wrapper.properties b/code/Java/Mobile/Application2.0/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..d067522 --- /dev/null +++ b/code/Java/Mobile/Application2.0/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Oct 06 09:52:26 MSK 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/code/Java/Mobile/Application2.0/gradlew b/code/Java/Mobile/Application2.0/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/code/Java/Mobile/Application2.0/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/code/Java/Mobile/Application2.0/gradlew.bat b/code/Java/Mobile/Application2.0/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/code/Java/Mobile/Application2.0/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/code/Java/Mobile/Application2.0/settings.gradle b/code/Java/Mobile/Application2.0/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/code/Java/Mobile/Application2.0/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/documentation/requirement.md b/documentation/requirement.md index ab69af0..ba9e469 100644 --- a/documentation/requirement.md +++ b/documentation/requirement.md @@ -11,13 +11,12 @@ 2. Нефункциональныые требования ## Введение - Название проекта: Android приложение для аппаратной платформы trackPlatform(далее аппаратная платформа или просто платформа). Вид проекта: программное обеспечение. Назначение данного проекта - это создание приложения для управления аппаратной платформой trackPlatform. ## Требования пользователя -### Прогрмааные интерфейсы +### Программные интерфейсы Приложение должно взаимодействовать с прошивкой аппаратной платформы по приведенному ниже протоколу. Взаимодействие с прошивкой будет осуществлятся по беспроводной связи(через Bluetooth). #### Протокол взаимодействия с аппаратной платформой @@ -62,6 +61,8 @@ платформе. ### Предположения и зависимости +На данные требования могут повлиять изменения в интерфейсе пользователя. Также на требования может +влиять добавление новых функциональных возможностей. ## Системные требования @@ -71,12 +72,15 @@ 3. Получение и вывод информации с датчиков расстояни. 4. Управление гусеницами прлатформы. 5. Управление сервоприводами платформы. -6. Поддержка двух языков интерфейса(русского и английского) +6. Поддержка двух языков интерфейса(русского и английского). +7. Приложение должно поддерживать несколько версий прошивки платформы(выбор прошивки +должен производиться в настройках приложения). ### Нефункциональныые требования Для данной системы важна надежность доставки сообщения. Так как если аппаратной платформе будет отправлено движение вперед, но команда "stop" будет потеряна, то платформа может совершить лишнее движение, которое может привести -к столкновению и, как следствие, порче оборудования. +к столкновению и, как следствие, порче оборудования. Под надежностью подразумевается возможность проверки на подленность +полученной команды(контрольная сумма). А также ответ на команду, который позволяет понять была ли выполненина команда. From cb8bc1885c4764f69489e3f576f0b03bbb7a89ed Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 8 Oct 2017 15:23:24 +0300 Subject: [PATCH 147/336] Some non-functional requirements were added --- docs/Requirements.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 13591e0..75e3527 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -14,7 +14,7 @@ 3) [Системные требования](#system_requires) 1) [Функциональные требования](#functional_requires) 2) [Нефункциональные требования](#nonfunctional_requires) - 1) [Атрибуты качаства](#quality_attributes) + @@ -203,13 +203,24 @@ в виде констант); 1. убрать поддержку редко используемых команд (неописанные старые команды); 1. заменить команды для датчиков на более расширяемые (см. список поддерживаемых команд); -1. оставить возможность одновременной поддержки нескольких версий API (версия API определяется по команде подключения) + ## Нефункциональные требования + + + +1. Масштабируемость: + - оставить возможность одновременной поддержки нескольких версий API (версия API определяется по команде подключения); + - добавить возможность расширения текущего функционала в будущем без: + - возможность изменения конфигурации платформы без перепрошивки модуля (пинов, настроек модулей) + - добавление новых датчиков прежнего вида без изменения API + - добавление новых датчиков с дополнением API +1. Надежность: + - платформа должна выполнять только те команды, которые дошли полнностью и без повреждений + + From 713f77cff61a10ac556bbf38c8294bad38fd8e41 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 8 Oct 2017 16:36:59 +0300 Subject: [PATCH 148/336] Quality attributes were fixed, limitations were added --- docs/Requirements.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 75e3527..896389c 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -14,7 +14,8 @@ 3) [Системные требования](#system_requires) 1) [Функциональные требования](#functional_requires) 2) [Нефункциональные требования](#nonfunctional_requires) - + 1) [Атрибуты качаства](#quality_attributes) + 1) [Ограничения](#limitations) @@ -209,18 +210,35 @@ ## Нефункциональные требования - +### Атрибуты качества +Данные требования должны быть учтены при проектировании и написании текущей прошивки: + 1. Масштабируемость: - оставить возможность одновременной поддержки нескольких версий API (версия API определяется по команде подключения); - добавить возможность расширения текущего функционала в будущем без: - - возможность изменения конфигурации платформы без перепрошивки модуля (пинов, настроек модулей) - - добавление новых датчиков прежнего вида без изменения API - - добавление новых датчиков с дополнением API + - возможность изменения конфигурации платформы без перепрошивки модуля (пинов, настроек модулей); + - добавление новых датчиков прежнего вида без изменения API; + - добавление новых датчиков с дополнением API; 1. Надежность: - - платформа должна выполнять только те команды, которые дошли полнностью и без повреждений - - + - платформа должна выполнять только те команды, которые дошли полностью и без повреждений: + - должно быть обеспечено протоколом передачи сообщений: длина сообщения и контрольная сумма. + + + +### Ограничения + +Разработка должна вестить на аппаратной платформе, которая совпадает с предыдущей версией: + +| Оборудование | Количество | +|:---|:---| +| Arduino Mega R3 | 1 шт. | +| Arduino Mega Sensor Shield v2.0 | 1 шт. | +| Датчики линии TCRT5000 | 5 шт. | +| Переходная плата для датчиков линии | 1 шт. | +| Датчики расстояния GP2Y0A21YK0F | 5 шт. | +| Переходная плата для датчиков расстояния | 1 шт. | +| Bluetooth HC-05 с переходной платой FC-114 | 1 шт. | From fa69c5ff1404a94d62a74daa89402446d70e8e56 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 8 Oct 2017 18:58:27 +0300 Subject: [PATCH 149/336] Quality attributes and limitations updating --- docs/Requirements.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/Requirements.md b/docs/Requirements.md index 896389c..7d050e3 100644 --- a/docs/Requirements.md +++ b/docs/Requirements.md @@ -219,10 +219,10 @@ 1. Масштабируемость: - оставить возможность одновременной поддержки нескольких версий API (версия API определяется по команде подключения); - - добавить возможность расширения текущего функционала в будущем без: + - добавить возможность дальнейшего расширения функционала: - возможность изменения конфигурации платформы без перепрошивки модуля (пинов, настроек модулей); - - добавление новых датчиков прежнего вида без изменения API; - - добавление новых датчиков с дополнением API; + - увеличение числа имеющихся датчиков (до 255 штук) без изменения API; + - добавление новых видов датчиков с дополнением API; 1. Надежность: - платформа должна выполнять только те команды, которые дошли полностью и без повреждений: - должно быть обеспечено протоколом передачи сообщений: длина сообщения и контрольная сумма. @@ -231,7 +231,7 @@ ### Ограничения -Разработка должна вестить на аппаратной платформе, которая совпадает с предыдущей версией: +Разработка должна вестить на аппаратной платформе, на которой была реализована предыдущая версия прошивки: | Оборудование | Количество | |:---|:---| @@ -242,3 +242,6 @@ | Датчики расстояния GP2Y0A21YK0F | 5 шт. | | Переходная плата для датчиков расстояния | 1 шт. | | Bluetooth HC-05 с переходной платой FC-114 | 1 шт. | +| Сервопривод SG-90 | 2 шт. | +| Драйвер двигателя L298N | 1 шт. | + From c2b6cef4fc28ed33564a2e9c230a5cc5c1c989ae Mon Sep 17 00:00:00 2001 From: Kimentii Date: Tue, 10 Oct 2017 12:14:05 +0300 Subject: [PATCH 150/336] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D1=82=D1=80=D0=B5=D0=B1?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=B3=D0=BB=D0=B0?= =?UTF-8?q?=D0=B2=D0=BD=D0=BE=D0=B5=20=D0=BC=D0=B5=D0=BD=D1=8E=20=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D1=81=D0=B8=D0=B9=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80?= =?UTF-8?q?=D1=84=D0=B5=D0=B9=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/requirement.md | 18 +++++++++++++----- documentation/user_interface/main_menu.png | Bin 0 -> 19196 bytes .../user_interface/motion_activity.png | Bin 0 -> 18409 bytes .../user_interface/sensors_activity.png | Bin 0 -> 38431 bytes .../user_interface/servo_activity.png | Bin 0 -> 15611 bytes .../user_interface/settings_activity.png | Bin 0 -> 17433 bytes 6 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 documentation/user_interface/main_menu.png create mode 100644 documentation/user_interface/motion_activity.png create mode 100644 documentation/user_interface/sensors_activity.png create mode 100644 documentation/user_interface/servo_activity.png create mode 100644 documentation/user_interface/settings_activity.png diff --git a/documentation/requirement.md b/documentation/requirement.md index ba9e469..60d257b 100644 --- a/documentation/requirement.md +++ b/documentation/requirement.md @@ -53,7 +53,7 @@ Только после этого настоятельно рекомендуется посылать следующую команду. ### Интерфес пользователя - +![](//user_interface/main_menu.png) ### Характреристики пользователей Данное приложение предназначено для пользователей имеющих базовые знания операционной системы Android. Пользователь должен уметь включать и отключать Bluetooth на своем устройстве, а также уметь подключиться @@ -70,11 +70,19 @@ 1. Поддержка беспроводной связи с платформой через Bluetooth. 2. Получение и вывод информации с датчиков линии. 3. Получение и вывод информации с датчиков расстояни. -4. Управление гусеницами прлатформы. +4. Управление гусеницами платформы. + 1. Движение веперд. + 2. Движение назад. + 3. Поворот по часовой стрелке. + 4. Поворот против часовой стрелке. + 5. Полная остановка. 5. Управление сервоприводами платформы. -6. Поддержка двух языков интерфейса(русского и английского). -7. Приложение должно поддерживать несколько версий прошивки платформы(выбор прошивки -должен производиться в настройках приложения). + 1. Установка угла отклонения для плоскости xy. + 2. Установка угла отклонения для плоскости xz. + 3. Получение угла отклонения по плоскости xy. + 4. Получение угла отклонения по плоскости xz. +6. Выбор языка(русского или английского). +7. Выбор нескольких версий прошивки платформы. ### Нефункциональныые требования Для данной системы важна надежность доставки сообщения. Так как если аппаратной платформе будет отправлено diff --git a/documentation/user_interface/main_menu.png b/documentation/user_interface/main_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..4bdeb467bbdaea23255190cccf8d9611a7c0718d GIT binary patch literal 19196 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 literal 0 HcmV?d00001 diff --git a/documentation/user_interface/motion_activity.png b/documentation/user_interface/motion_activity.png new file mode 100644 index 0000000000000000000000000000000000000000..7146d4e3bad8cf57d59d44bfd915b0829106c8ae GIT binary patch literal 18409 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 literal 0 HcmV?d00001 diff --git a/documentation/user_interface/sensors_activity.png b/documentation/user_interface/sensors_activity.png new file mode 100644 index 0000000000000000000000000000000000000000..aa851e84cad0b6864385aba971f69ed312ff51b6 GIT binary patch literal 38431 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%0A;upB*STBv>T7d*bjwttM zPoKj6VhrVC+csvu(T$FUQ-2=pLm}w^nbw^{Cs-52i0VLkBRWUC%19t!_<`4UxaS#{ zQ+tTRk)$K8Z6$oTiR40jaPcYF6a-y+II!@@(?Kz;!aIXD(Yj1GmwhP^qR1YK<%;XR z400%la54S#0wqDWZP>41U{tHoVT|T z5nQAe;){SyEJ|@vvbKBCj2J&+CeT1PAryi&4%rY!Mi8x}GbbVS>`62$d3Fp=a;#04 z@a7($>KmqPz{kXMR)xQYeb~Bij9icR{cL2eTw90NLVHp%0MB?m?*Pmx?&u7988tmQ zDe0|k3Tcr=nNxPlbUAp@Nr&p3unj^VxcY80Z19uDr89~W z+Z*cZRZu}{;Dis4tK`&`RDC7W&d!b$uJmMRYF2W`=$^sc_=1~7vrWo%eivo5W-91DIYgz zqIMV&6Wmvzq)E}1&jY=*s`ic54|Kec#x*v69!Dj35?Z5rE~EmIJAjuHew_Z**%f+Q zv8(N_PM_IxoM59*?d>fRdajTC5u`=}-QHht020lO4|Y4}6Tx7+vZ zxjeUX&7*%9mzxGHHNN8uM{K}#nxgl_kPDCPzyVc!;6PBJBnJX`3eE(?a z`Tmp15*Hayz0~77uQme^0l;82Rel`&^2yapA&*V;Bxa4Vx?!z9h^+(PqV=SpBq>Mx zGuN@FvzI-FBkcSb2nZSi^#=Fftl6{iykLxOXhmx1>C|oWSNaxaO37HQ1(<~Pw0SV; zw8HX6hE3ZPkTDoMP@fcAVkoLO9(h@=9PYN@Cb_c z{d)%EugNd{Ec#(FCkp9Yg`ziW>M4IE^mE_`A-ziO?eTtd1gJXzUonS*YBRKDIb-D` zlVMjz!g1pgn!m^G9H{m`ELvoQ5gx(b(aL-%gt%+49nV{^VDPop*HDDddgBZY0XU4Y zFH!=`->D03PSJpi0t^oxyo_MKb6&{1iF<&1?s)2HNGHKq=HPc&gdWBJz3=9;KK66g z{jZ>f?nCwAG*F!XfDn_j0Vap~!p5jZJw)SLK75IKsQ25Pm&#;icUHsiwJp(o`o5aK z*@EvgH-Enj7Z98eAo(gWu{Q9Fu&#rIJ5z6kto89d7 ze`mEIU*86dGoZq(8q#H(J2B=0Tj0df6{{AaSJe8#Xkxq$4@5Qj;4%>*8X9?d?b~)> zF2Vf#d~`TR0180mp*;QVaE`j%fohB=q^?0>j7lqCn*TIFSg#@YcsZiqeo;I zcUQobE883#k{LAytoQpVOw>vn!Tr8#6sIn!mq3=yH-FM5_)MV9n zgV9CPQ!uc00&c8w6M#W@Q1y#Jxa{Iu25;c&*IH0I`(H!lJyT$v^Fqr0`Zw4ijp}?C zemv16%8?U1?OacAa9NB`D}8fEsBO*)juU+KaME`os4&GC1x_4dUX&50j-k$bbGCFZ zi25r7@pRj-48(RUYFn{9Yh%6TVWhFuYbTC`mTI@`hS>+u;Mg9NZ24Z!0`@Hmg52!% z`rCizA}0BL3%JrK@OaHI6BvKd-wA86?R4+PM|E?$b)!*l79^TY$>Fmcmbr52)giy16Gd7bHjOX`w4|rT zuwsil?YBG$^&U;BS&{BC=Jav2JS7eLMJu`<&D;ZyH8Wlt`I160W#oS`JFRnP4#BOu z6lpLcY3l}8&2AJ}zNhv+pNFu=4igg-^!qfRYNty(>&gndwvs|@Oyvy?4d?W1J8s{@ z)F$Q4yTCN>-hQbzYf?*82v6^j% z#xuy!39iEo?l3O#nnZv%y=wm1IEWaa$>evgvw#0egtiziPvHyH6($Gb_IY@C zVEB|g_U`!-ho{cTXrh#ZT7(Lg-R9<<^4j$5>`iDZbItV?m|ZOwJJ5bC1FvX{W-@rz zjqyB{{nWV(xA^78~EO4I0P*8|^$` zMVtq#Q$&>wmSpg;TD22(|{o>rZ%%8Cxsfu~fx54PM>%hCFpsS+~^#;a`nQpN28i5xJgi7x7D?W6@ z{j-9@1xmqlR%cy>?O%T&CFT_Umkd;Y2Iu(-Yz&43)COvolSwNrE4z%^iS}zcR)t97 zzR0r+fu$f=aBL_a4;;}!drcrhCEVA!#24ySY}dlFMzc&I2>F0zu+Z;TQ&U60BA87Z zYQF_;9&Ohv;beRA;e?B`v+YpNTN1IbmTm6>4T}bH$uZI}HPj8EDd6SHmk`E8@q%0R zySut9waxKbkS~BidPS^8&8j4Z)(gto-Z^%!f0sGrG~+pfH0I-4epSeuYW|`J9^K*2 zUv?c2NJ8hMAH0jC>R(7&&`>HhqP`5@NJj5;KV&KZxA5K(WbU3VD@0p71M}h>zOjMi ztPm8YNawB9PY*(qrZBFV#kTaMBpgmLh559Bc#+t4OgN~%+KuMI{=C=dC1l{r&`{ZE z9$Z^ndjk(3T0bXnWg*B77@4D7M=HXsE?PEbZp5Y3CB1^JVEf*r*qMMx30j7wPz>Ar z*~PJ0!S;x_(BK>>0-Rn{%P)CEnO96V2#<5P)3GC`NjtOW%-WW#`}GU)e^*phT_eqe z`vLy+dwQ{i3 zYOF%?9q<`mOR5v()$m+@4HH~S}(IN_? zZ|JtY?{WbIs3@;30Kq^Qt`?->H1Py2KVUh@!n-qF+;N|_AoZGph?rfY+h8jQfMM7h z{h(_dL1q8eEh$)KzyNJ1rre1KJ77c$!llovnL1b+dxD>M@yHc-Wi|`aaYw?{;s-Tq zHA2ZnC}ajRGP1;=ll%l|CtQNYvlplxan(~u=q$rESQf}indLM4CExjBO86diPkNX_ z*u0ghv#!4?FZah|Hqu)aKc;rZE-QpzFXZIOlcL&*_c|2lAj_8(`t@!Gi|zsxTRSuw zN$bDQ{8dR|7anYd{g+V)ulJfp7p$y~?ru6tHy_!y7A-5pD2az01(O>FAJFWyHMULJ z6Cbp!vRDJIts(}d7DnhcBR%j52+=L!2&K6>lV>#;oUlagM-d+N;HJ{K!JX-d#UFy+ zgy>6_^cym36^0Ad7=u}38-e@_@E$j+P$7BRwRusaW39ms#ivaIqw*n=WPc2gpa{}j zHz=?=)V!37bfmQ_=I4(rQnTS8i$jDIXRrcp{`*rJ1+c&VM`r&ZFH$= zUraOh;1V1tP)|P@qZm)6_J?$jfhPR{m$Ig}pE5Hum&DEX$r%1=*oHn012C(?52HZ< zYPqBagi)M!9fOWI1fbpid2aUu#XS3G1{Oe?vHU5cK>4+7eTktxaE8V% ziGwG8Y?psTbfOno|58gi1nP8B>I7c&*Cd#z!DP^Z8_vUYp&<3*@JTM$TN2V9Z054S zj|W&;G6g6gF5y`_fY^DcEAZog}5GRpctz~lS$!P*l+Uy>Tb>bfip!X-hI)cSKR)8`? zTb!lD+li0sU4*WPE%^g(4L$Ik-I9&Vp@l*X>b6h&K7*?K(5!wlD zJCM9L`SeEo(6{N(KpCZ5x%B$v6pKJeS2Q$)!nhQfk+HGxu3atUz7p8Pm0WSvD$1*? zWtKWffrM6baB#rm*fv=BuBN(;97j(~IX3;Osw#)XP;6Psq153Ef*TjclB={{;E)6W z*q*_M7jR!e(h$bQxemn5<7+VvRt`M}JYr_;@!*l7TvYrcRQgLS^}oL`fhqs@JN)l= i_hzNF{sW?X50O-?tCFy$$#laz3Tk$|Z^i*fhCv zEYvC+2(fWn(6#&K-);f*M{C?p`}8SWvQNqI=FOWhVinft=~K4Gz`=Y7yWH#SNw*p; zEiKYk2agN3%xb{j!eZ~&XI^7t9#7Sgey)WnBf4}FVT+G|n?7^WS@8hiwZG$|W-s=K?_kX(esM2@C znzCwhYT)ElOePWXN-b(M5w31^IZqy+KYyP6uB}>q`>@Mk@rv(~9sT*$#oEcilhWRp zdM8~EU1b}2L^@A~PY0^cak^WtdUY%2B@G)0Q+Hig?g0b>K^7G~F*i4tDrt*gO6CjP zY^58obc(kWPwwjK%H8=%|C+B!US57cdO4iVy-I+&MD;7$l-@>r-~;C`7XOCLzMOE2 z3@$+>C|zB{mKM8$$$Gxgp|%eaHnhShA$mK<_Dh5OA^qrqQKNg}3JNtYl{LR5Bra*{ zZWg#8F^B6LR(SwYDBe7=H$0^!==U}t;#!iPDZs@-tN zrobZ+;F_5EqT1T06E#q1`9+2808Pzs%_uf^$5797$M=tJb=pizm2oHYnuZb-ME2jJ zi#8Ug;}wOaVHQ@M;zYkW-Nc5i8XpM>@3o67r@M*?pH!t_7D6-FOw+8vJ#cVgc5`*7 zlE3L>HmOsRC3ytwese7D`qXseRty?RYV_ywGdUAqRlKeO#K2E%KT5LqQ@&#eSBHLJ zV575(i}y+~LUaGBgjsn$B!pL0P*8C7&x_c^2_hrU-y>6U+*1BReE!PfyV|Q73rY4vd>XYfC5~!D!oa{5% z$qrkc_fT?2n(ux?ngsFb!IJLlDS;dN>a;E%KH41S}AIK&tZa%VDv^r5v3_Ng7lYuC5$I`-&WPxWG-<@k4 zKiMoDIEp+8%8EH8qO`bzbIbc`Er0Hu3_4EfG?NQClPzwA<&l`G0a`&K~WKd6AG zfy3ca>3N#b2G5`8@;SAHPCpAx$=tn%9R z>x$J&6H!kdvnQmK(8OAZgCjlbnCT&XrGJov&do~VrV-5^5=SMXe2^oVvRCEBbql2q zix&0j9-MYr?*3^>$ts6l{uM{aAe#aomEBd%{gL&_T-+&KJ#P4D?bPW$H2XPvr7My} zXd+L|&Mf{&@vXEi2w!-nx)I#4$G~=VtFiE0`mOKgRyO4~&tPm~;ym9TeKxs5y)5w# z_k>jTDe#Jiv~`UKC%A*tGs?iwP*J|=mOoCM*Z?j&Ie3B7m$ zox$HJl6gDErl#5ouRnBN<<%4t6-61&uRcaHg(Y0u(4VeUAE8}Y^scXRHciQV+Mr*x zyGsw*#wa%BjAX=#Ly!~oqDzz$<*+zDJx!my3FYFO><1Z}L9^1+@`~&;wZAt7;K8EZ z@$*9Bd9r{>$TMzRRg8Fet0zm59DpPQdnc;z12mriS$b|Y^+O%kE{7$|xUUZ7-p8HnA;`G5 zBjy$Lme#%p*(iUP>eV{E8lhg|%I3brTE=NZ{$|reRB;6dE?H?#ZqfRn>Jj`#^;2rv z5bn8|p^uDBxJ3`)D;FFmYu!^7eapCmkGINrhE6br?Hz=L);g`|eLQd<u%3MuT`|PPWZiDDzZd z&Mpb=-1kK>Is_ z=jU$kNB?Ho`i&F1OT}&*>x?m##6L6)AZ4QkQhq`LGXuNSV_;9 zw*=KxU&}1@g0kt+d@3vIF(S;6uUa zCCD!xF!CY|GyP+3#Ea#l z>ioXRQ{z!WGScJlh(3Y%S@fQnQ%6Qgt#uv!$YIsiI$HKnWooJH9Sc28^RTznus>-!AnLp?0l@eRb;=?cRfg<#Tn@9g3T3NW9Q^L@>Z z$o!l@!SiljvUx2Rymi@tPIxC$t86Ci+ zJ26lHqI^Cb$25eWLcPhgwVS6_;_`ICghv&gVeCB<-1RmvqqEo4lz(LRZ+#&)BVw /// Contains true if Line is white, else false /// public bool[] Line { get; } = new bool[LineNum]; + + public string SelectedPort { get; set; } + public uint Speed { get; } = 9600; + + public bool IsConnected + { + get => _maskIsConnected; + set => ChangeProperty(ref value, ref _maskIsConnected, nameof(IsConnected)); + } + + private readonly ApiManager _api; + + public MainWindowViewModel() + { + ApiManager.SensorCallback lineCallback = (index, value) => + { + Line[index] = (value == LineWhite); + OnPropertyChanged(nameof(Line)); + }; + ApiManager.SensorCallback distanceCallback = (index, value) => + { + Distanse[index] = value; + OnPropertyChanged(nameof(Distanse)); + }; + + _api = new ApiManager(distanceCallback, lineCallback); + } + + /// + /// Connect to device with selected configuration + /// + /// true, if successfully connected, else false + private bool Connect() + { + bool res = _api.ConnectToDevice(SelectedPort, Speed); + IsConnected = res; + return res; + } + + /// + /// Disconnect from device + /// + private void Disconnect() + { + _api.Disconnect(); + IsConnected = false; + } + + /// + /// Toggle connection to device + /// + /// true if all is successful, else false + public bool ToggleConnection() + { + try + { + if (IsConnected) + { + Disconnect(); + return true; + } + + return Connect(); + } + catch (Exception e) + { + MessageBox.Show(e.Message, "We have an error", MessageBoxButton.OK, MessageBoxImage.Error); + IsConnected = false; + return false; + } + } } } \ No newline at end of file From d7ba74640af4813bfff735e28cb301e4a27e6ee4 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sat, 9 Dec 2017 22:31:07 +0300 Subject: [PATCH 309/336] IDisposable implementation was added to unmanaged resources --- code/c#/Sample App/ApiManager.cs | 25 ++++++++++++++++++++++- code/c#/Sample App/MainWindow.xaml.cs | 6 ++++++ code/c#/Sample App/MainWindowViewModel.cs | 8 +++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/code/c#/Sample App/ApiManager.cs b/code/c#/Sample App/ApiManager.cs index 474cbcc..ebdbdd8 100644 --- a/code/c#/Sample App/ApiManager.cs +++ b/code/c#/Sample App/ApiManager.cs @@ -3,7 +3,7 @@ namespace Sample_App { - public class ApiManager + public class ApiManager : IDisposable { private const string DllName = "cxx.unmanaged.dll"; @@ -35,6 +35,11 @@ public ApiManager(SensorCallback distanceCallback, SensorCallback lineCallback) /// true, if connectio was successful, else false public bool ConnectToDevice(string comAddress, uint speed) { + if (_unmanagedPtr != IntPtr.Zero) + { + return false; + } + _unmanagedPtr = Connect(comAddress, speed); if (_unmanagedPtr == IntPtr.Zero) { @@ -50,8 +55,26 @@ public bool ConnectToDevice(string comAddress, uint speed) /// public void Disconnect() { + if (_unmanagedPtr == IntPtr.Zero) return; + Disconnect(_unmanagedPtr); _unmanagedPtr = IntPtr.Zero; } + + private void ReleaseUnmanagedResources() + { + Disconnect(); + } + + public void Dispose() + { + ReleaseUnmanagedResources(); + GC.SuppressFinalize(this); + } + + ~ApiManager() + { + ReleaseUnmanagedResources(); + } } } \ No newline at end of file diff --git a/code/c#/Sample App/MainWindow.xaml.cs b/code/c#/Sample App/MainWindow.xaml.cs index d4ac714..a6fbcf5 100644 --- a/code/c#/Sample App/MainWindow.xaml.cs +++ b/code/c#/Sample App/MainWindow.xaml.cs @@ -26,6 +26,12 @@ public MainWindow() { InitializeComponent(); _vm = DataContext as MainWindowViewModel; + + //Dispose resources + Dispatcher.ShutdownStarted += (sender, args) => + { + _vm.Dispose(); + }; } private void OnConnectClicked(object sender, RoutedEventArgs e) diff --git a/code/c#/Sample App/MainWindowViewModel.cs b/code/c#/Sample App/MainWindowViewModel.cs index f7e815c..c80199e 100644 --- a/code/c#/Sample App/MainWindowViewModel.cs +++ b/code/c#/Sample App/MainWindowViewModel.cs @@ -1,10 +1,11 @@ using System; using System.ComponentModel; using System.Windows; +using System.Windows.Threading; namespace Sample_App { - public class MainWindowViewModel : INotifyPropertyChanged + public class MainWindowViewModel : INotifyPropertyChanged, IDisposable { #region INotifyPropertyChanged implementation @@ -124,5 +125,10 @@ public bool ToggleConnection() return false; } } + + public void Dispose() + { + _api?.Dispose(); + } } } \ No newline at end of file From 98a61e3952a7a84ca75e3942f966782f6afc98c1 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 16:39:54 +0300 Subject: [PATCH 310/336] Introduction was added --- docs/TestPlan.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 904b03e..329d0e5 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -2,8 +2,22 @@ ### Введение +Данный план описывает тестирование всей системы. + +Требования, предъявляемые к тестировщику: + +* умение упралять смартфоном или персональным компьютером (далее, ПК) + +* умение подключать смартфон или ПК к другому устройству по интерфейсу Bluetooth или USB + +* понимание механизма работы портов последовательного обмена информацией (COM-портов, Serial-портов) + +Цель данного тестирования: проверка работоспособности системы в реальных условиях + ### Объект тестирования +Прошивка для микроконтроллера ATmega 2560, который расположен на Arduino Mega 2560 R3. + ### Риски ### Аспекты тестирования From 12a7b35e76c1f95648b47583a70df0373413b6d7 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 19:22:05 +0300 Subject: [PATCH 311/336] Test Items description was added --- docs/TestPlan.md | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 329d0e5..108beff 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -2,21 +2,36 @@ ### Введение -Данный план описывает тестирование всей системы. +Данный план описывает тестирование всей системы. Требования, предъявляемые к тестировщику: -* умение упралять смартфоном или персональным компьютером (далее, ПК) - +* умение управлять смартфоном или персональным компьютером (далее, ПК) * умение подключать смартфон или ПК к другому устройству по интерфейсу Bluetooth или USB - * понимание механизма работы портов последовательного обмена информацией (COM-портов, Serial-портов) Цель данного тестирования: проверка работоспособности системы в реальных условиях -### Объект тестирования - -Прошивка для микроконтроллера ATmega 2560, который расположен на Arduino Mega 2560 R3. +### Объекты тестирования + +* Прошивка для микроконтроллера ATmega 2560, который расположен на Arduino Mega 2560 R3 +* Корректная работа всей платформы +* API, предоставляемое прошивкой для управление периферийными устройствами микроконтроллера + +Атрибуты качества прошивки по ISO 25010: + +* функциональность + * функциональная полнота: платформа должна выполнять все возложенные на нее функции (см. [Функциональные требования](Requirements.md#functional_requires)) + * функциональная корректность: платформа должна выполнять все возложенные на нее функции корректно (см. [Функциональные требования](Requirements.md#functional_requires)) +* производительность + * временная характеристика: платформа должна реагировать на каждую команду не более 1 секунды +* практичность + * защита от ошибок пользователей: платформа должна работать только согласно [протоколу](Requirements.md#protocol) и проверять аргументы каждой команды +* сопровождаемость + * модульность: все периферийные модули должны взаимодействовать с протоколом через специальный модуль взаимодействия, протокол взаимодействия должен знать каждый модуль взаимодействия, все должно быть организовано через специальный класс +* мобильность + * устанавливаемость: прошивка должна корректно устанавливаться и работать на любой Arduino Mega с аналогичной оригинальной периферией + * заменяемость: прошивка должна в полной мере заменить свою предыдущую версию ### Риски From d067236d1a53bf59cd0ec773d346dc72ef20e1ef Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 19:57:22 +0300 Subject: [PATCH 312/336] Risks, features to be tested & testing strategy were written --- docs/TestPlan.md | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 108beff..107a1b5 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -35,17 +35,39 @@ ### Риски -### Аспекты тестирования +Без корректной работы протокола невозможна работа всей платформы в целом -Что описывать: +### Аспекты тестирования -Use cases +* возможность подключения к платформе; +* возможность принудительного отключения от платформы; +* автоматическое отключение от платформы по истечению определенного промежутка времени; +* управление гусеничной платформой (управление движением): + - движение вперед; + - движение назад; + - разворот по направлению движения часовой стрелки; + - разворот против направления движения часовой стрелки; +* взаимодействие с поворотной платформой: + - управление поворотной платформой: + - поворот в плоскости xy; + - поворот в плоскости xz; + - получение информации о текущем состоянии сервоприводов: + - получение текущего угла отклонения в плоскости xy; + - получение текущего угла отклонения в плоскости xz; +* получение корректной информации с датчиков линии (с "заводской" калибровкой датчиков в виде констант); +* получение корректной информации с датчиков расстояния (с "заводской" калибровкой датчиков в виде констант); +* время жизни от батареи должно быть не менее 5 минут (с учетом полностью заряженной батареи в начале теста); +* реакция на любую команду должна составлять не более 1 секунды; + +### Функции, не подлежащие тестированию + +//TODO -Время жизни от батареи (минимум 5 минут) +### Подходы к тестированию -реакция (не более 1 секунды) +Для тестирования можно использовать как приложение для ПК, так и приложение для смартфона. -### Подходы к тестированию +При тестировании через ПК-версию приложения рекомендуется использовать версию приложения для клавиатуры, т.к. она предоставляет полные возможности API в отличии от версии для геймпада ### Представление результатов From dc4fb916a8d8c66f2c17a4132eb622ecc9b1c59a Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 20:37:18 +0300 Subject: [PATCH 313/336] First test cases were made --- docs/TestPlan.md | 43 +++++++++++++++++- .../mega_sensor_shield_loaded.jpg | Bin 0 -> 57293 bytes 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 docs/TestPlan_images/mega_sensor_shield_loaded.jpg diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 107a1b5..2d209fa 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -18,7 +18,7 @@ * Корректная работа всей платформы * API, предоставляемое прошивкой для управление периферийными устройствами микроконтроллера -Атрибуты качества прошивки по ISO 25010: +Атрибуты качества платформы по ISO 25010: * функциональность * функциональная полнота: платформа должна выполнять все возложенные на нее функции (см. [Функциональные требования](Requirements.md#functional_requires)) @@ -61,7 +61,7 @@ ### Функции, не подлежащие тестированию -//TODO +Не требуется тестирование атрибута качества "Защита от ошибок пользователей", поскольку он выполняется на уровне API языка высокого уровня. ### Подходы к тестированию @@ -71,4 +71,43 @@ ### Представление результатов +Предоставление результатов требуется описать в следующем виде: + +1. Идентификатор +2. Назначение / название +3. Сценарий +4. Ожидаемый результат +5. Фактический результат (заполняется на этапе тестирования) +6. Оценка (заполняется на этапе тестирования) + +Далее приведены сами тестовые сценарии + +#### Возможность подключения к платформе + +1. 1 + +2. Возможность подключения к платформе + +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы (на изображении ниже светодиод 1 должен отключиться (перестать моргать), а светодиод 2 должен гореть) + + ![mega_loaded](TestPlan_images/mega_sensor_shield_loaded.jpg) + + 3. Запустите приложение и попробуйте подключиться к платформе + +4. В приложении появится надпись "Connected" + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выйдите из приложения, через которое подключались (нажмите кнопку "Quit") + 3. Попробуйте заново подключиться к платформе +4. В приложении, с помощью которого производилось подключение второй раз, появится надпись "Connected" + ### Выводы \ No newline at end of file diff --git a/docs/TestPlan_images/mega_sensor_shield_loaded.jpg b/docs/TestPlan_images/mega_sensor_shield_loaded.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d0e4d2fa7bfdf05ed1ca1b0a332d9c0ba8f9e0f6 GIT binary patch literal 57293 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 z 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�FMvWV8037aL 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 U1kjWBPvKM1MMwn{Q9vL6*)CYc&j0`b literal 0 HcmV?d00001 From a566b38cb29d1425f00e32f94955387061ad62d9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 21:13:21 +0300 Subject: [PATCH 314/336] Test cases 3 - 11 were added --- docs/TestPlan.md | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 2d209fa..4fd91c3 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -110,4 +110,89 @@ 3. Попробуйте заново подключиться к платформе 4. В приложении, с помощью которого производилось подключение второй раз, появится надпись "Connected" +#### Автоматическое отключение от платформы по истечению определенного промежутка времени + +1. 3 +2. Автоматическое отключение от платформы по истечению определенного промежутка времени +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Аварийно завершить работу приложения, через которое производилось подключение, либо принудительно разорвать соединение (выдернуть USB-провод или отключить Bluetooth-соединение) + 3. Подождите 10 секунд + 4. Попробуйте заново подключиться к платформе +4. В приложении, с помощью которого производилось подключение второй раз, появится надпись "Connected" + +#### Движение вперед + +1. 4 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "move forward". Если требуется, укажите скорость +4. Платформа должна поехать вперед с заданной скоростью + +#### Движение назад + +1. 5 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "move back". Если требуется, укажите скорость +4. Платформа должна поехать назад с заданной скоростью + +#### Разворот по направлению движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "turn right (clockwise)". Если требуется, укажите скорость +4. Платформа должна начать поворачиваться с заданной скоростью по часовой стрелке + +#### Разворот против направления движения часовой стрелки + +1. 7 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "turn left (anticlockwise)". Если требуется, укажите скорость +4. Платформа должна начать поворачиваться с заданной скоростью против часовой стрелки + +#### Поворот сервоприводов в плоскости xy + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set horisontal servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) +4. Платформа должна установить сервоприводы на указанный угол + +#### Поворот сервоприводов в плоскости xz + +1. 9 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set vertical servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) +4. Платформа должна установить сервоприводы на указанный угол + +#### Получение текущего угла отклонения в сервоприводов в плоскости xy + +1. 10 +2. Получение текущего угла отклонения в сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set horisontal servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) + 3. Выберите в приложении "get horisontal servo angle in degree" +4. В приложении должно появится значение, которое было введено в пункте 3.2 + +#### Получение текущего угла отклонения в сервоприводов в плоскости xz + +1. 11 +2. Получение текущего угла отклонения в сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set vertical servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) + 3. Выберите в приложении "get vertical servo angle in degree" +4. В приложении должно появится значение, которое было введено в пункте 3.2 + ### Выводы \ No newline at end of file From a5f534f3c2c29f0722191a85171c0e7df82101c1 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 21:49:03 +0300 Subject: [PATCH 315/336] Test cases 12-16 were added --- docs/TestPlan.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 4fd91c3..0f4bb18 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -195,4 +195,52 @@ 3. Выберите в приложении "get vertical servo angle in degree" 4. В приложении должно появится значение, которое было введено в пункте 3.2 -### Выводы \ No newline at end of file +#### Некорректный поворот сервоприводов в плоскости xy + +1. 12 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set horisontal servo angle in degree". Укажите некорректный угол в градусах (больше 180) +4. Платформа не должна изменить текущий угол сервоприводов + +#### Некорректный поворот сервоприводов в плоскости xz + +1. 13 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set vertical servo angle in degree". Укажите некорректный угол в градусах (больше 180) +4. Платформа не должна изменить текущий угол сервоприводов + +#### Получение информации с датчиков линии. Белый лист + +1. 14 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Выберите в приложении "get fixed line value". Укажите номер датчика в диапазоне от 1 до 5 +4. В приложении должно появится 0 + +#### Получение информации с датчиков линии. Черный лист + +1. 15 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Выберите в приложении "get fixed line value". Укажите номер датчика в диапазоне от 1 до 5 +4. В приложении должно появится 1 + +#### Получение информации с датчиков расстояния + +1. 16 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Выберите в приложении "get fixed distance value". Укажите номер датчика 3 +4. В приложении должно появится значение от 10 до 19 + +### Выводы From 85c962f3911017c7ef64052bd6adbad6303ed010 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 22:21:43 +0300 Subject: [PATCH 316/336] Test cases 17 & 18 were added --- docs/TestPlan.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 0f4bb18..7681217 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -243,4 +243,23 @@ 3. Выберите в приложении "get fixed distance value". Укажите номер датчика 3 4. В приложении должно появится значение от 10 до 19 +#### Проверка времени жизни от батареи + +1. 17 +2. Проверка времени жизни от батареи. +3. Произведите следующие шаги: + 1. Зарядите аккомуляторную батарею платформы до 100% + 2. Подключитесь к платформе + 3. Повзаимодействуйте с платформой 5 минут +4. Платформа все еще должна работать + +#### Проверка времени реакции на любую команду + +1. 18 +2. Проверка времени реакции на любую команду. Она должна составлять не более 1 секунды +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выполните любую команду +4. Платформа должна среагировать (вернуть ответ или совершить действие) быстрее, чем за 2 секунды + ### Выводы From 0e9f29fd418011f47bd94ac26c7ee6c217211a3c Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 23:23:59 +0300 Subject: [PATCH 317/336] Conclusion was added. features not to be tested were fixed. --- docs/TestPlan.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 7681217..7f1405f 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -27,6 +27,8 @@ * временная характеристика: платформа должна реагировать на каждую команду не более 1 секунды * практичность * защита от ошибок пользователей: платформа должна работать только согласно [протоколу](Requirements.md#protocol) и проверять аргументы каждой команды +* надежность + * доступность: платформа должна работать от аккомуляторной батареи не менее 5 минут * сопровождаемость * модульность: все периферийные модули должны взаимодействовать с протоколом через специальный модуль взаимодействия, протокол взаимодействия должен знать каждый модуль взаимодействия, все должно быть организовано через специальный класс * мобильность @@ -61,7 +63,11 @@ ### Функции, не подлежащие тестированию -Не требуется тестирование атрибута качества "Защита от ошибок пользователей", поскольку он выполняется на уровне API языка высокого уровня. +Не требуется тестирование атрибута качества "Защита от ошибок пользователей" для всех пунктов меню, поскольку он выполняется на уровне API языка высокого уровня. + +Атрибут качества "Устанавливаемость" предполагает наличие еще одной платформы, а она отсуствует вообще. + +Атрибут качества "Модульность" должен выполняться на этапе проектирования исходных кодов прошивки, поэтому также не будет протестирован вообще. ### Подходы к тестированию @@ -263,3 +269,19 @@ 4. Платформа должна среагировать (вернуть ответ или совершить действие) быстрее, чем за 2 секунды ### Выводы + +В вышеописанных тестовых сценариях проверяется выполнение атрибутов качества. Зависимость проверки представлена ниже: + +| Атрибут качества | В каких тестовых сценариях проверяется | +| ------------------------------ | -------------------------------------- | +| Функциональная полнота | 1-16 | +| Функциональная корректность | 1-16 | +| Временная характеристика | 18 | +| Доступность | 17 | +| Защита от ошибок пользователей | 12-13 | +| Модульность | - | +| Устанавливаемость | - | +| Заменяемость | 1-16 | + + + From 28d96c7d80d49854240a57a4178aed2955d6f7b5 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Sun, 10 Dec 2017 23:39:15 +0300 Subject: [PATCH 318/336] Some test plan fixes --- docs/TestPlan.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index 7f1405f..b3e082f 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -10,7 +10,7 @@ * умение подключать смартфон или ПК к другому устройству по интерфейсу Bluetooth или USB * понимание механизма работы портов последовательного обмена информацией (COM-портов, Serial-портов) -Цель данного тестирования: проверка работоспособности системы в реальных условиях +Цель данного тестирования: проверка работоспособности системы в реальных условиях. ### Объекты тестирования @@ -266,11 +266,11 @@ 3. Произведите следующие шаги: 1. Подключитесь к платформе 2. Выполните любую команду -4. Платформа должна среагировать (вернуть ответ или совершить действие) быстрее, чем за 2 секунды +4. Платформа должна среагировать (вернуть ответ или совершить действие) быстрее, чем за 1 секунду ### Выводы -В вышеописанных тестовых сценариях проверяется выполнение атрибутов качества. Зависимость проверки представлена ниже: +В вышеописанных тестовых сценариях проверяется выполнение атрибутов качества. Зависимость представлена ниже: | Атрибут качества | В каких тестовых сценариях проверяется | | ------------------------------ | -------------------------------------- | @@ -283,5 +283,7 @@ | Устанавливаемость | - | | Заменяемость | 1-16 | +Если не выполняется один из тестовых сценариев, то, соответственно, не выполняется и соответствующий атрибут качества. Продукт будет обладать требуемыми атрибутами качества только при выполнении всех тестовых сценариев. +Функциональные и нефункциональные требования из [SRS](Requirements.md) проверяются в тестовых сценариях 1-16. From 396f8a62926dfa0f930fa3027d5dcb772cae3627 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Sun, 10 Dec 2017 23:55:49 +0300 Subject: [PATCH 319/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82?= =?UTF-8?q?=D0=B0=D1=82=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/TestCases.md | 217 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 docs/TestCases.md diff --git a/docs/TestCases.md b/docs/TestCases.md new file mode 100644 index 0000000..951fe47 --- /dev/null +++ b/docs/TestCases.md @@ -0,0 +1,217 @@ +#### Возможность подключения к платформе + +1. 1 + +2. Возможность подключения к платформе + +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы (на изображении ниже светодиод 1 должен отключиться (перестать моргать), а светодиод 2 должен гореть) + + ![mega_loaded](TestPlan_images/mega_sensor_shield_loaded.jpg) + + 3. Запустите приложение и попробуйте подключиться к платформе + +4. В приложении появится надпись "Connected" + +5. В левом верхнем углу появилась надпись "Connected" + +6. Прошел + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выйдите из приложения, через которое подключались (нажмите кнопку "Quit") + 3. Попробуйте заново подключиться к платформе +4. В приложении, с помощью которого производилось подключение второй раз, появится надпись "Connected" +5. При нажатии кнопки "Exit" приложение завершилось. При втором открытии приложения надпись "Connected" появилась. +6. Прошел + +#### Автоматическое отключение от платформы по истечению определенного промежутка времени + +1. 3 +2. Автоматическое отключение от платформы по истечению определенного промежутка времени +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Аварийно завершить работу приложения, через которое производилось подключение, либо принудительно разорвать соединение (выдернуть USB-провод или отключить Bluetooth-соединение) + 3. Подождите 10 секунд + 4. Попробуйте заново подключиться к платформе +4. В приложении, с помощью которого производилось подключение второй раз, появится надпись "Connected" +5. Соединение установилось +6. Прошел + +#### Движение вперед + +1. 4 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "move forward". Если требуется, укажите скорость +4. Платформа должна поехать вперед с заданной скоростью +5. Платформа поехала вперед +6. Прошел + +#### Движение назад + +1. 5 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "move back". Если требуется, укажите скорость +4. Платформа должна поехать назад с заданной скоростью +5. Платформа поезала назад +6. Прошел + +#### Разворот по направлению движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "turn right (clockwise)". Если требуется, укажите скорость +4. Платформа должна начать поворачиваться с заданной скоростью по часовой стрелке +5. Платформа повернулась по часовой стрелке +6. Прошел + +#### Разворот против направления движения часовой стрелки + +1. 7 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "turn left (anticlockwise)". Если требуется, укажите скорость +4. Платформа должна начать поворачиваться с заданной скоростью против часовой стрелки +5. Платформа повернулась против часовой стрелки +6. Прошел + +#### Поворот сервоприводов в плоскости xy + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set horisontal servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) +4. Платформа должна установить сервоприводы на указанный угол +5. Нет такого функцианала +6. Не прошел + +#### Поворот сервоприводов в плоскости xz + +1. 9 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set vertical servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) +4. Платформа должна установить сервоприводы на указанный угол +5. Нет такого функцианала +6. Не прошел + +#### Получение текущего угла отклонения в сервоприводов в плоскости xy + +1. 10 +2. Получение текущего угла отклонения в сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set horisontal servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) + 3. Выберите в приложении "get horisontal servo angle in degree" +4. В приложении должно появится значение, которое было введено в пункте 3.2 +5. Нет такого функцианала +6. Не прошел + +#### Получение текущего угла отклонения в сервоприводов в плоскости xz + +1. 11 +2. Получение текущего угла отклонения в сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set vertical servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) + 3. Выберите в приложении "get vertical servo angle in degree" +4. В приложении должно появится значение, которое было введено в пункте 3.2 +5. Нет такого функцианала +6. Не прошел + +#### Некорректный поворот сервоприводов в плоскости xy + +1. 12 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set horisontal servo angle in degree". Укажите некорректный угол в градусах (больше 180) +4. Платформа не должна изменить текущий угол сервоприводов +5. Нет такого функцианала +6. Не прошел + +#### Некорректный поворот сервоприводов в плоскости xz + +1. 13 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выберите в приложении "set vertical servo angle in degree". Укажите некорректный угол в градусах (больше 180) +4. Платформа не должна изменить текущий угол сервоприводов +5. Нет такого функцианала +6. Не прошел + +#### Получение информации с датчиков линии. Белый лист + +1. 14 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Выберите в приложении "get fixed line value". Укажите номер датчика в диапазоне от 1 до 5 +4. В приложении должно появится 0 +5. Информация с датчиков была получена +6. Прошел + +#### Получение информации с датчиков линии. Черный лист + +1. 15 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Выберите в приложении "get fixed line value". Укажите номер датчика в диапазоне от 1 до 5 +4. В приложении должно появится 1 +5. Нет такого функцианала +6. Не прошел + +#### Получение информации с датчиков расстояния + +1. 16 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Выберите в приложении "get fixed distance value". Укажите номер датчика 3 +4. В приложении должно появится значение от 10 до 19 +5. Информация с датчиков была получена +6. Прошел + +#### Проверка времени жизни от батареи + +1. 17 +2. Проверка времени жизни от батареи. +3. Произведите следующие шаги: + 1. Зарядите аккомуляторную батарею платформы до 100% + 2. Подключитесь к платформе + 3. Повзаимодействуйте с платформой 5 минут +4. Платформа все еще должна работать +5. Платформа реагировала на взаимодействие +6. Прошел + +#### Проверка времени реакции на любую команду + +1. 18 +2. Проверка времени реакции на любую команду. Она должна составлять не более 1 секунды +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Выполните любую команду +4. Платформа должна среагировать (вернуть ответ или совершить действие) быстрее, чем за 1 секунду +5. Платформа реагирует на команды +6. Прошел \ No newline at end of file From af1323c1660a1cce801b8aef9d56fad7b3d54ce9 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 11 Dec 2017 00:02:04 +0300 Subject: [PATCH 320/336] TestPlan: one definition fix --- docs/TestPlan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/TestPlan.md b/docs/TestPlan.md index b3e082f..13f9509 100644 --- a/docs/TestPlan.md +++ b/docs/TestPlan.md @@ -32,7 +32,7 @@ * сопровождаемость * модульность: все периферийные модули должны взаимодействовать с протоколом через специальный модуль взаимодействия, протокол взаимодействия должен знать каждый модуль взаимодействия, все должно быть организовано через специальный класс * мобильность - * устанавливаемость: прошивка должна корректно устанавливаться и работать на любой Arduino Mega с аналогичной оригинальной периферией + * устанавливаемость: прошивка должна корректно устанавливаться и работать на любой Arduino Mega с аналогичной оригинальной платформе периферией * заменяемость: прошивка должна в полной мере заменить свою предыдущую версию ### Риски From c8d69dac49d5e3e12f55aba33b47f42f991b7315 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 11 Dec 2017 09:14:54 +0300 Subject: [PATCH 321/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=BA=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0=D1=82=D0=B0=D0=BC=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/TestCases.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/TestCases.md b/docs/TestCases.md index 951fe47..c59ad2d 100644 --- a/docs/TestCases.md +++ b/docs/TestCases.md @@ -214,4 +214,21 @@ 2. Выполните любую команду 4. Платформа должна среагировать (вернуть ответ или совершить действие) быстрее, чем за 1 секунду 5. Платформа реагирует на команды -6. Прошел \ No newline at end of file +6. Прошел + +### Выводы + +Выполняются пункты: 1-7, 14, 16, 17, 18. + +| Атрибут качества | Результат(в %) | +| ------------------------------ | -------------- | +| Функциональная полнота | 56 | +| Функциональная корректность | 56 | +| Временная характеристика | 61 | +| Доступность | 59 | +| Защита от ошибок пользователей | 0 | +| Модульность | - | +| Устанавливаемость | - | +| Заменяемость | 56 | + +Видно, что продукт не обладает защитой от ошибок пользователя. \ No newline at end of file From 844c4340f332eea9a2f6e2e01b6953afa41d5ba9 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 11 Dec 2017 22:39:35 +0300 Subject: [PATCH 322/336] =?UTF-8?q?=D0=92=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5,=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D1=8B=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F,=20=D1=80=D0=B8=D1=81=D0=BA=D0=B8=20=D0=B3=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=D1=8B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/test_plan.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 documentation/test_plan.md diff --git a/documentation/test_plan.md b/documentation/test_plan.md new file mode 100644 index 0000000..e4b5b77 --- /dev/null +++ b/documentation/test_plan.md @@ -0,0 +1,37 @@ +# План тестирования + +### Введение + +Данный план описывает тестирование приложения для управления аппаратной платформой. + +Требования, предъявляемые к тестировщику: + +* умение пользоваться устройством под управлением операционной системы Android(далее смартфон). +* умение подключать смартфон к другому устройству по интерфейсу Bluetooth. + +Цель данного тестирования: проверка работоспособности системы в реальных условиях. + +### Объекты тестирования + +* Приложение для операционной системы Android. + +Атрибуты качества платформы по ISO 25010: + +* функциональность + * функциональная полнота: приложение должно выполнять все возложенные на нее функции + * функциональная корректность: приложение должно выполнять все возложенные на нее функции корректно +* производительность + * временная характеристика: приложение должно открываться не медленнее чем за 30 секунд +* практичность + * защита от ошибок пользователей: приложение должно выводить сообщения об ошибках если пользователь произвел некорректное действие +* надежность + * доступность: приложение должно работать при автономной работе смартфомна не менее 5 минут +* сопровождаемость + * модульность: взаимодействие с платформой должно осуществляться через Connector, который при необходимости можно заменить +* мобильность + * устанавливаемость: приложение должно корректно работать на любом смартфоне с версией Android выше 4.2 и модулем Bluetooth. + +### Риски + +При некорректной работе приложения можно повредить аппаратную платформу. + From 9693a518246efc3299faef98ebce08cc5416a6a3 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Mon, 11 Dec 2017 23:08:30 +0300 Subject: [PATCH 323/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BF=D1=83=D0=BD=D0=BA=D1=82=D1=8B=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/test_plan.md | 148 +++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/documentation/test_plan.md b/documentation/test_plan.md index e4b5b77..1930a9f 100644 --- a/documentation/test_plan.md +++ b/documentation/test_plan.md @@ -35,3 +35,151 @@ При некорректной работе приложения можно повредить аппаратную платформу. +### Аспекты тестирования + +* возможность подключения к платформе; +* возможность принудительного отключения от платформы; +* управление гусеничной платформой (управление движением): + - движение вперед; + - движение назад; + - разворот по направлению движения часовой стрелки; + - разворот против направления движения часовой стрелки; +* взаимодействие с поворотной платформой: + - управление поворотной платформой: + - поворот в плоскости xy; + - поворот в плоскости xz; +* получение корректной информации с датчиков линии; +* получение корректной информации с датчиков расстояния; + +### Подходы к тестированию + +Для тестирования необходим смартфон под управлением операционной системы Android версии 4.2 и выше. В смартфоне должен находиться исправный модель Bluetooth. + +### Представление результатов + +Предоставление результатов требуется описать в следующем виде: + +1. Идентификатор +2. Назначение / название +3. Сценарий +4. Ожидаемый результат +5. Фактический результат (заполняется на этапе тестирования) +6. Оценка (заполняется на этапе тестирования) + +Тестовые сценарии: + +#### Возможность подключения к платформе + +1. 1 + +2. Возможность подключения к платформе + +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы + + 3. Запустите приложение + +4. В приложении появится надпись "Connected" + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Нажать кнопку Exit в главном меню приложения + 3. Попробуйте заново подключиться к платформе +4. В приложении, появится надпись "Connected" + +#### Движение вперед + +1. 3 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "forward" +4. Платформа должна поехать вперед + +#### Движение назад + +1. 4 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "back" +4. Платформа должна поехать назад + +#### Разворот по направлению движения часовой стрелки + +1. 5 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "right" +4. Платформа должна начать поворачиваться по часовой стрелке + +#### Разворот против направления движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "left" +4. Платформа должна начать поворачиваться против часовой стрелки + +#### Поворот сервоприводов в плоскости xy + +1. 7 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку right +4. Платформа должна изменить угол отклонения сервопривода + +#### Поворот сервоприводов в плоскости xz + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку "up" +4. Платформа должна поднять сервопривод вверх + +#### Получение информации с датчиков линии. Белый лист + +1. 9 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 0 + +#### Получение информации с датчиков линии. Черный лист + +1. 10 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 1 + +#### Получение информации с датчиков расстояния + +1. 11 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Нажмите на кнопку "Sensors" +4. В приложении должно появится значение от 10 до 19 \ No newline at end of file From a5aac3ee4e7bdba507cf075380e0d5e434853bf4 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Tue, 12 Dec 2017 09:26:32 +0300 Subject: [PATCH 324/336] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BD=D1=8B=D0=B5=20=D1=84=D0=BE=D1=80=D0=BC=D1=83=D0=BB?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/test_plan.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/documentation/test_plan.md b/documentation/test_plan.md index 1930a9f..2d60623 100644 --- a/documentation/test_plan.md +++ b/documentation/test_plan.md @@ -9,13 +9,11 @@ * умение пользоваться устройством под управлением операционной системы Android(далее смартфон). * умение подключать смартфон к другому устройству по интерфейсу Bluetooth. -Цель данного тестирования: проверка работоспособности системы в реальных условиях. - ### Объекты тестирования * Приложение для операционной системы Android. -Атрибуты качества платформы по ISO 25010: +Атрибуты качества приложения по ISO 25010: * функциональность * функциональная полнота: приложение должно выполнять все возложенные на нее функции From a25df312f4bbb17e96f79ff838b5ec8e5771fda0 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Tue, 12 Dec 2017 16:03:59 +0300 Subject: [PATCH 325/336] Test cases passing was added --- documentation/test_cases.md | 149 ++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 documentation/test_cases.md diff --git a/documentation/test_cases.md b/documentation/test_cases.md new file mode 100644 index 0000000..465058c --- /dev/null +++ b/documentation/test_cases.md @@ -0,0 +1,149 @@ +# Проверка тестовых сценариев + +## Представление результатов + +Предоставление результатов требуется описать в следующем виде: + +1. Идентификатор +2. Назначение / название +3. Сценарий +4. Ожидаемый результат +5. Фактический результат (заполняется на этапе тестирования) +6. Оценка (заполняется на этапе тестирования) + +## Тестовые сценарии: + +#### Возможность подключения к платформе + +1. 1 +2. Возможность подключения к платформе +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы + + 3. Запустите приложение +4. В приложении появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Нажать кнопку Exit в главном меню приложения + 3. Попробуйте заново подключиться к платформе +4. В приложении, появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Движение вперед + +1. 3 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "forward" +4. Платформа должна поехать вперед +5. Платформа поехала вперед +6. Выполнен + +#### Движение назад + +1. 4 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "back" +4. Платформа должна поехать назад +5. Платформа поехала назад +6. Выполнен + +#### Разворот по направлению движения часовой стрелки + +1. 5 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "right" +4. Платформа должна начать поворачиваться по часовой стрелке +5. Платформа начала поворачиваться по часовой стрелке +6. Выполнен + +#### Разворот против направления движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "left" +4. Платформа должна начать поворачиваться против часовой стрелки +5. Платформа начала поворачиваться против часовой стрелки +6. Выполнен + +#### Поворот сервоприводов в плоскости xy + +1. 7 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку right +4. Платформа должна изменить угол отклонения сервопривода +5. Сервопривод на платформе повернулся вправо +6. Выполнен + +#### Поворот сервоприводов в плоскости xz + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку "up" +4. Платформа должна поднять сервопривод вверх +5. Сервопривод на платформе повернулся вверх +6. Выполнен + +#### Получение информации с датчиков линии. Белый лист + +1. 9 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 0 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков линии. Черный лист + +1. 10 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 1 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков расстояния + +1. 11 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Нажмите на кнопку "Sensors" +4. В приложении должно появится значение от 10 до 19 +5. В приложении появилось значение 21 напротив значения центрального датчика +6. Не выполнен \ No newline at end of file From 2d89f255e63f6c01635b0799bb57080679a52a40 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 13 Dec 2017 11:13:12 +0300 Subject: [PATCH 326/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B8=20=D0=B5=D0=B3=D0=BE=20=D1=80=D0=BE=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BE=D1=81=D0=BF=D0=BE=D1=81=D0=BE=D0=B1=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activities/SensorsActivity.java | 16 +++- .../kimentii/application20/api/API.java | 1 + .../kimentii/application20/api/API1.java | 7 +- .../kimentii/application20/api/API2.java | 8 +- .../kimentii/application20/api/API3.java | 7 +- .../kimentii/application20/api/API4.java | 28 +++++-- .../connectors/BluetoothConnector.java | 73 +++++++++++++++++-- .../application20/constants/Constants.java | 5 +- .../controllers/ServoController.java | 16 ++-- 9 files changed, 131 insertions(+), 30 deletions(-) diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/activities/SensorsActivity.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/activities/SensorsActivity.java index 25c5d17..4e77542 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/activities/SensorsActivity.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/activities/SensorsActivity.java @@ -101,8 +101,20 @@ protected void onCreate(Bundle savedInstanceState) { Handler handler = new Handler() { @Override public void handleMessage(Message msg) { - if (msg.what == Constants.Messages.MESSAGES_READ.getValue()) { - + if (msg.what == Constants.Messages.MESSAGES_READ_DISTANCE_SENSORS_VALUES.getValue()) { + int data[] = (int[]) msg.obj; + firstDistanceSensorValueTV.setText(String.valueOf(data[0])); + secondDistanceSensorValueTV.setText(String.valueOf(data[1])); + thirdDistanceSensorValueTV.setText(String.valueOf(data[2])); + fourthDistanceSensorValueTV.setText(String.valueOf(data[3])); + fifthDistanceSensorValueTV.setText(String.valueOf(data[4])); + } else if (msg.what == Constants.Messages.MESSAGES_READ_LINE_SENSORS_VALUES.getValue()) { + int data[] = (int[]) msg.obj; + firstLineSensorValueTV.setText(String.valueOf(data[0])); + secondLineSensorValueTV.setText(String.valueOf(data[1])); + thirdLineSensorValueTV.setText(String.valueOf(data[2])); + fourthLineSensorValueTV.setText(String.valueOf(data[3])); + fifthLineSensorValueTV.setText(String.valueOf(data[4])); } } diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API.java index 69a5074..0b5e998 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API.java @@ -18,6 +18,7 @@ public Constants.ApiEnum getApiEnum() { public abstract byte[] getDisconnectCommand(); + public abstract byte[] getReconnectCommand(); // motion activity public abstract byte[] getMoveForwardCommand(); diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API1.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API1.java index d7e8cf2..5d64887 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API1.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API1.java @@ -18,6 +18,11 @@ public byte[] getDisconnectCommand() { return new byte[0]; } + @Override + public byte[] getReconnectCommand() { + return new byte[0]; + } + @Override public byte[] getMoveForwardCommand() { return new byte[0]; @@ -74,4 +79,4 @@ public byte[] getInfoFromAllLineSensorsCommand() { return new byte[0]; } -} +} \ No newline at end of file diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API2.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API2.java index cc544a0..f92df56 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API2.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API2.java @@ -1,6 +1,5 @@ package com.example.kimentii.application20.api; - import com.example.kimentii.application20.constants.Constants; public class API2 extends API { @@ -19,6 +18,11 @@ public byte[] getDisconnectCommand() { return new byte[0]; } + @Override + public byte[] getReconnectCommand() { + return new byte[0]; + } + @Override public byte[] getMoveForwardCommand() { return new byte[0]; @@ -74,4 +78,4 @@ public byte[] getInfoFromAllLineSensorsCommand() { return new byte[0]; } -} +} \ No newline at end of file diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API3.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API3.java index 677e0d1..a4ee745 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API3.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API3.java @@ -18,6 +18,11 @@ public byte[] getDisconnectCommand() { return new byte[0]; } + @Override + public byte[] getReconnectCommand() { + return new byte[0]; + } + @Override public byte[] getMoveForwardCommand() { return new byte[0]; @@ -73,4 +78,4 @@ public byte[] getInfoFromAllDistanceSensorsCommand() { public byte[] getInfoFromAllLineSensorsCommand() { return new byte[0]; } -} +} \ No newline at end of file diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API4.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API4.java index 2000969..99e71c2 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API4.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/api/API4.java @@ -8,6 +8,7 @@ public class API4 extends API { public final String TAG = "TAG"; + public API4() { apiEnum = Constants.ApiEnum.API4; } @@ -36,10 +37,21 @@ public byte[] getDisconnectCommand() { return command; } + @Override + public byte[] getReconnectCommand() { + byte command[] = {(byte) 0x02, Constants.Controllers.COMMUNICATION_CONTROLLER_ID.getValue(), + Constants.Communication.REFRESH_CONNECTION.getValue(), (byte) 0x00, (byte) 0x00}; + CRC16Modbus crc = new CRC16Modbus(); + crc.update(command, 0, command.length - CRC16Modbus.SIZE_CRC_IN_BYTES); + command[command.length - 2] = (byte) ((crc.getValue() & 0x000000ff)); + command[command.length - 1] = (byte) ((crc.getValue() & 0x0000ff00) >>> 8); + return command; + } + @Override public byte[] getMoveForwardCommand() { - byte command[] = {(byte) 0x04, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), - Constants.Movement.FORWARD_WITH_SPEED.getValue(), (byte) '5', (byte) '0', + byte command[] = {(byte) 0x05, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), + Constants.Movement.FORWARD_WITH_SPEED.getValue(), (byte) '1', (byte) '5', (byte) '0', (byte) 0x00, (byte) 0x00}; CRC16Modbus crc = new CRC16Modbus(); crc.update(command, 0, command.length - CRC16Modbus.SIZE_CRC_IN_BYTES); @@ -50,8 +62,8 @@ public byte[] getMoveForwardCommand() { @Override public byte[] getMoveRightCommand() { - byte command[] = {(byte) 0x04, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), - Constants.Movement.TURN_IN_CLOCK_ARROW_DIRECTION.getValue(), (byte) '5', (byte) '0', + byte command[] = {(byte) 0x05, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), + Constants.Movement.TURN_IN_CLOCK_ARROW_DIRECTION.getValue(), (byte) '1', (byte) '5', (byte) '0', (byte) 0x00, (byte) 0x00}; CRC16Modbus crc = new CRC16Modbus(); crc.update(command, 0, command.length - 2); @@ -62,8 +74,8 @@ public byte[] getMoveRightCommand() { @Override public byte[] getMoveLeftCommand() { - byte command[] = {(byte) 0x05, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), - Constants.Movement.TURN_IN_CLOCK_ARROW_DIRECTION.getValue(), (byte) '-', (byte) '5', + byte command[] = {(byte) 0x06, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), + Constants.Movement.TURN_IN_CLOCK_ARROW_DIRECTION.getValue(), (byte) '-', (byte) '1', (byte) '5', (byte) '0', (byte) 0x00, (byte) 0x00}; CRC16Modbus crc = new CRC16Modbus(); crc.update(command, 0, command.length - CRC16Modbus.SIZE_CRC_IN_BYTES); @@ -74,8 +86,8 @@ public byte[] getMoveLeftCommand() { @Override public byte[] getMoveBackCommand() { - byte command[] = {(byte) 0x05, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), - Constants.Movement.FORWARD_WITH_SPEED.getValue(), (byte) '-', (byte) '5', + byte command[] = {(byte) 0x06, Constants.Controllers.MOVEMENT_CONTROLLER_ID.getValue(), + Constants.Movement.FORWARD_WITH_SPEED.getValue(), (byte) '-', (byte) '1', (byte) '5', (byte) '0', (byte) 0x00, (byte) 0x00}; CRC16Modbus crc = new CRC16Modbus(); crc.update(command, 0, command.length - CRC16Modbus.SIZE_CRC_IN_BYTES); diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/connectors/BluetoothConnector.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/connectors/BluetoothConnector.java index 6dd6bc3..bea6d52 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/connectors/BluetoothConnector.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/connectors/BluetoothConnector.java @@ -4,6 +4,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.os.Handler; +import android.os.Message; import android.util.Log; import com.example.kimentii.application20.constants.Constants; @@ -13,7 +14,11 @@ import java.io.DataOutputStream; import java.io.IOException; import java.lang.reflect.Method; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +// необзодимо переработать отсылку команд. ГУИ должно добавлять команду в буфер, а поток со +// связью должен брать команды из очереди и выполнять их public class BluetoothConnector extends Thread { public static final String TAG = "TAG"; @@ -114,16 +119,43 @@ public void run() { write(Settings.getInstance().getApi().getConnectCommand(Settings.getInstance().getApi().getApiEnum())); byte buf[] = new byte[100]; setRepeat(true); + Thread autoConnector = new Thread() { + private int DELAY_TIME_IM_MS = 4000; + + @Override + public void run() { + while (isRepeat()) { + write(Settings.getInstance().getApi().getReconnectCommand()); + try { + for (int i = 0; i < 5; i++) { + synchronized (dataInputStream) { + dataInputStream.read(); + } + } + Thread.sleep(DELAY_TIME_IM_MS); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }; + autoConnector.start(); while (isRepeat()) { try { - int dataSize = dataInputStream.read(); - byte buf2[] = new byte[dataSize]; - for (int j = 0; j < dataSize; j++) { - buf2[j] = dataInputStream.readByte(); + int dataSize; + byte buf2[]; + synchronized (dataInputStream) { + dataSize = dataInputStream.read(); + buf2 = new byte[dataSize]; + for (int j = 0; j < dataSize; j++) { + buf2[j] = dataInputStream.readByte(); + } + // read CTC + dataInputStream.read(); + dataInputStream.read(); } - // read CTC - dataInputStream.read(); - dataInputStream.read(); String str = ""; String strChar = ""; for (int i = 0; i < dataSize; i++) { @@ -132,7 +164,32 @@ public void run() { } Log.d(TAG, str); Log.d(TAG, strChar); - + if (strChar.equals("OK")) { + continue; + } else if (strChar.equals("ERROR")) { + continue; + } else { + Pattern p = Pattern.compile("([0-9]{1,3})(;)" + + "([0-9]{1,3})(;)" + "([0-9]{1,3})(;)" + "([0-9]{1,3})(;)" + "([0-9]{1,3})"); + Matcher matcher = p.matcher(strChar); + if (matcher.find()) { + Log.d(TAG, "GOOOOOOOOD"); + Log.d(TAG, "Group count: " + matcher.groupCount()); + int data[] = new int[5]; + for (int i = 0, j = 1; i < 5; i++, j += 2) { + data[i] = Integer.parseInt(matcher.group(j)); + } + if (matcher.group(1).equals("1") || matcher.group(1).equals("0")) { + Message message = handler.obtainMessage(Constants.Messages.MESSAGES_READ_LINE_SENSORS_VALUES.getValue(), + data.length, -1, data); + message.sendToTarget(); + } else { + Message message = handler.obtainMessage(Constants.Messages.MESSAGES_READ_DISTANCE_SENSORS_VALUES.getValue(), + data.length, -1, data); + message.sendToTarget(); + } + } + } } catch (IOException e) { e.printStackTrace(); } diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/constants/Constants.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/constants/Constants.java index 6251c0d..d482db4 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/constants/Constants.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/constants/Constants.java @@ -1,7 +1,7 @@ package com.example.kimentii.application20.constants; public interface Constants { - String BLUETOOTH_MAC = "20:16:04:11:37:56"; + String BLUETOOTH_MAC = "00:21:13:03:71:23"; enum ApiEnum { API1((byte) 0x01), @@ -112,7 +112,8 @@ public byte getValue() { } enum Messages { - MESSAGES_READ(1); + MESSAGES_READ_DISTANCE_SENSORS_VALUES(1), + MESSAGES_READ_LINE_SENSORS_VALUES(2); private int value; diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/controllers/ServoController.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/controllers/ServoController.java index e65e51d..8da389d 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/controllers/ServoController.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/controllers/ServoController.java @@ -20,7 +20,8 @@ public ServoController() { public void turnUpOnOneDegree() { BluetoothConnector bluetoothConnector = BluetoothConnector.getInstance(); API api = Settings.getInstance().getApi(); - if (angleXZ + 1 <= 180) { + if (angleXZ + 5 <= 180) { + angleXZ += 5; bluetoothConnector.write(api.getSetAngleCommand(++angleXZ, API.XZ)); } } @@ -28,7 +29,8 @@ public void turnUpOnOneDegree() { public void turnRightOnOneDegree() { BluetoothConnector bluetoothConnector = BluetoothConnector.getInstance(); API api = Settings.getInstance().getApi(); - if (angleXY + 1 <= 180) { + if (angleXY + 5 <= 180) { + angleXY += 5; bluetoothConnector.write(api.getSetAngleCommand(++angleXY, API.XY)); } } @@ -36,16 +38,18 @@ public void turnRightOnOneDegree() { public void turnLeftOnOneDegree() { BluetoothConnector bluetoothConnector = BluetoothConnector.getInstance(); API api = Settings.getInstance().getApi(); - if (angleXY - 1 >= 0) { - bluetoothConnector.write(api.getSetAngleCommand(--angleXY, API.XY)); + if (angleXY - 5 >= 0) { + angleXY -= 5; + bluetoothConnector.write(api.getSetAngleCommand(angleXY, API.XY)); } } public void turnDownOnOneDegree() { BluetoothConnector bluetoothConnector = BluetoothConnector.getInstance(); API api = Settings.getInstance().getApi(); - if (angleXZ - 1 >= 0) { - bluetoothConnector.write(api.getSetAngleCommand(--angleXZ, API.XZ)); + if (angleXZ - 5 >= 0) { + angleXZ -= 5; + bluetoothConnector.write(api.getSetAngleCommand(angleXZ, API.XZ)); } } } From f167ee5a5f387401fbe4ae1ef2b2f4189eea123f Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 13 Dec 2017 11:56:50 +0300 Subject: [PATCH 327/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4,=20=D0=B8=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D1=81=D0=BC=D0=B5=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=8F=D0=B7=D1=8B=D0=BA=D0=B0=20=D0=B8=20API.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/test_plan.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/documentation/test_plan.md b/documentation/test_plan.md index 2d60623..fa5586b 100644 --- a/documentation/test_plan.md +++ b/documentation/test_plan.md @@ -180,4 +180,36 @@ 1. Подключитесь к платформе 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров 3. Нажмите на кнопку "Sensors" -4. В приложении должно появится значение от 10 до 19 \ No newline at end of file +4. В приложении должно появится значение от 10 до 19 + +#### Смена языка + +1. 12 +2. Смена языка интерфеса +3. Произведите следующие шаги: + 1. Нажмите на кнопку "Settings" в главном меню + 2. Измените язык +4. В приложении должен измениться язык интерфейса + +#### Выбор другого API + +1. 13 +2. Смена API +3. Произведите следующие шани: + 1. Нажмите на кнопку "Settings" в главном меню + 2. Выберите дргой API +4. Приложение должно продолжать работу, все команды пользователя должны выполняться + +### Вывод + +Данные тесты показывают выполенние функциональных требований. Соответсвите функциональных требований и тестов: + +| Функциональные требования | ID теста | +| ---------------------------------------- | :------: | +| Поддержка беспроводной связи с платформой через Bluetooth | 1-2 | +| Получение и вывод информации с датчиков линии | 9-10 | +| Получение и вывод информации с датчиков расстояни | 11 | +| Управление гусеницами платформы | 3-6 | +| Управление сервоприводами платформы | 7-8 | +| Выбор языка (русского или английского) | 12 | +| Выбор нескольких версии API для взаимодействия с платформой | 13 | \ No newline at end of file From 727f68b14545999a2b0b001bdd0840910e57d0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B5=D0=B2?= Date: Wed, 13 Dec 2017 12:07:00 +0300 Subject: [PATCH 328/336] Add files via upload Test cases --- documentation/test_cases.md.txt | 149 ++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 documentation/test_cases.md.txt diff --git a/documentation/test_cases.md.txt b/documentation/test_cases.md.txt new file mode 100644 index 0000000..465058c --- /dev/null +++ b/documentation/test_cases.md.txt @@ -0,0 +1,149 @@ +# Проверка тестовых сценариев + +## Представление результатов + +Предоставление результатов требуется описать в следующем виде: + +1. Идентификатор +2. Назначение / название +3. Сценарий +4. Ожидаемый результат +5. Фактический результат (заполняется на этапе тестирования) +6. Оценка (заполняется на этапе тестирования) + +## Тестовые сценарии: + +#### Возможность подключения к платформе + +1. 1 +2. Возможность подключения к платформе +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы + + 3. Запустите приложение +4. В приложении появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Нажать кнопку Exit в главном меню приложения + 3. Попробуйте заново подключиться к платформе +4. В приложении, появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Движение вперед + +1. 3 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "forward" +4. Платформа должна поехать вперед +5. Платформа поехала вперед +6. Выполнен + +#### Движение назад + +1. 4 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "back" +4. Платформа должна поехать назад +5. Платформа поехала назад +6. Выполнен + +#### Разворот по направлению движения часовой стрелки + +1. 5 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "right" +4. Платформа должна начать поворачиваться по часовой стрелке +5. Платформа начала поворачиваться по часовой стрелке +6. Выполнен + +#### Разворот против направления движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "left" +4. Платформа должна начать поворачиваться против часовой стрелки +5. Платформа начала поворачиваться против часовой стрелки +6. Выполнен + +#### Поворот сервоприводов в плоскости xy + +1. 7 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку right +4. Платформа должна изменить угол отклонения сервопривода +5. Сервопривод на платформе повернулся вправо +6. Выполнен + +#### Поворот сервоприводов в плоскости xz + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку "up" +4. Платформа должна поднять сервопривод вверх +5. Сервопривод на платформе повернулся вверх +6. Выполнен + +#### Получение информации с датчиков линии. Белый лист + +1. 9 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 0 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков линии. Черный лист + +1. 10 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 1 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков расстояния + +1. 11 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Нажмите на кнопку "Sensors" +4. В приложении должно появится значение от 10 до 19 +5. В приложении появилось значение 21 напротив значения центрального датчика +6. Не выполнен \ No newline at end of file From b84a5d136678ebfd26f2277402c54cc4dfe42860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B5=D0=B2?= Date: Wed, 13 Dec 2017 12:09:45 +0300 Subject: [PATCH 329/336] Delete test_cases.md.txt --- documentation/test_cases.md.txt | 149 -------------------------------- 1 file changed, 149 deletions(-) delete mode 100644 documentation/test_cases.md.txt diff --git a/documentation/test_cases.md.txt b/documentation/test_cases.md.txt deleted file mode 100644 index 465058c..0000000 --- a/documentation/test_cases.md.txt +++ /dev/null @@ -1,149 +0,0 @@ -# Проверка тестовых сценариев - -## Представление результатов - -Предоставление результатов требуется описать в следующем виде: - -1. Идентификатор -2. Назначение / название -3. Сценарий -4. Ожидаемый результат -5. Фактический результат (заполняется на этапе тестирования) -6. Оценка (заполняется на этапе тестирования) - -## Тестовые сценарии: - -#### Возможность подключения к платформе - -1. 1 -2. Возможность подключения к платформе -3. Произведите следующие шаги: - - 1. Включите платформу - - 2. Дождитесь загрузки платформы - - 3. Запустите приложение -4. В приложении появится надпись "Connected" -5. В приложении появилась надпись "Connected" -6. Выполнен - -#### Возможность принудительного отключения от платформы - -1. 2 -2. Возможность принудительного отключения от платформы по завершению работы с ней -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Нажать кнопку Exit в главном меню приложения - 3. Попробуйте заново подключиться к платформе -4. В приложении, появится надпись "Connected" -5. В приложении появилась надпись "Connected" -6. Выполнен - -#### Движение вперед - -1. 3 -2. Проверка движения платформы вперед -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "forward" -4. Платформа должна поехать вперед -5. Платформа поехала вперед -6. Выполнен - -#### Движение назад - -1. 4 -2. Проверка движения платформы назад -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "back" -4. Платформа должна поехать назад -5. Платформа поехала назад -6. Выполнен - -#### Разворот по направлению движения часовой стрелки - -1. 5 -2. Проверка возможности поворота платформы по часовой стрелке -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "right" -4. Платформа должна начать поворачиваться по часовой стрелке -5. Платформа начала поворачиваться по часовой стрелке -6. Выполнен - -#### Разворот против направления движения часовой стрелки - -1. 6 -2. Проверка возможности поворота платформы против часовой стрелки -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "left" -4. Платформа должна начать поворачиваться против часовой стрелки -5. Платформа начала поворачиваться против часовой стрелки -6. Выполнен - -#### Поворот сервоприводов в плоскости xy - -1. 7 -2. Проверка возможности поворота сервоприводов в плоскости xy -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Servo" - 3. Нажмите на кнопку right -4. Платформа должна изменить угол отклонения сервопривода -5. Сервопривод на платформе повернулся вправо -6. Выполнен - -#### Поворот сервоприводов в плоскости xz - -1. 8 -2. Проверка возможности поворота сервоприводов в плоскости xz -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Servo" - 3. Нажмите на кнопку "up" -4. Платформа должна поднять сервопривод вверх -5. Сервопривод на платформе повернулся вверх -6. Выполнен - -#### Получение информации с датчиков линии. Белый лист - -1. 9 -2. Получение информации с датчиков линии. Проверка корректного определения белого цвета -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Положите под платформу лист белой бумаги - 3. Нажмите на кнопку "Sensors" -4. В приложении напротив нумерации датчиков линии должно появиться значение 0 -5. Были значения как 0, так и 1 -6. Не выполнен - -#### Получение информации с датчиков линии. Черный лист - -1. 10 -2. Получение информации с датчиков линии. Проверка корректного определения черного цвета -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Положите под платформу лист черной бумаги - 3. Нажмите на кнопку "Sensors" -4. В приложении напротив нумерации датчиков линии должно появиться значение 1 -5. Были значения как 0, так и 1 -6. Не выполнен - -#### Получение информации с датчиков расстояния - -1. 11 -2. Получение информации с датчиков расстояния -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров - 3. Нажмите на кнопку "Sensors" -4. В приложении должно появится значение от 10 до 19 -5. В приложении появилось значение 21 напротив значения центрального датчика -6. Не выполнен \ No newline at end of file From b8e257119643e66f06489b089491e017f10aa4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B5=D0=B2?= Date: Wed, 13 Dec 2017 12:10:22 +0300 Subject: [PATCH 330/336] Add files via upload Tests added --- documentation/tests.md | 149 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 documentation/tests.md diff --git a/documentation/tests.md b/documentation/tests.md new file mode 100644 index 0000000..465058c --- /dev/null +++ b/documentation/tests.md @@ -0,0 +1,149 @@ +# Проверка тестовых сценариев + +## Представление результатов + +Предоставление результатов требуется описать в следующем виде: + +1. Идентификатор +2. Назначение / название +3. Сценарий +4. Ожидаемый результат +5. Фактический результат (заполняется на этапе тестирования) +6. Оценка (заполняется на этапе тестирования) + +## Тестовые сценарии: + +#### Возможность подключения к платформе + +1. 1 +2. Возможность подключения к платформе +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы + + 3. Запустите приложение +4. В приложении появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Нажать кнопку Exit в главном меню приложения + 3. Попробуйте заново подключиться к платформе +4. В приложении, появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Движение вперед + +1. 3 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "forward" +4. Платформа должна поехать вперед +5. Платформа поехала вперед +6. Выполнен + +#### Движение назад + +1. 4 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "back" +4. Платформа должна поехать назад +5. Платформа поехала назад +6. Выполнен + +#### Разворот по направлению движения часовой стрелки + +1. 5 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "right" +4. Платформа должна начать поворачиваться по часовой стрелке +5. Платформа начала поворачиваться по часовой стрелке +6. Выполнен + +#### Разворот против направления движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "left" +4. Платформа должна начать поворачиваться против часовой стрелки +5. Платформа начала поворачиваться против часовой стрелки +6. Выполнен + +#### Поворот сервоприводов в плоскости xy + +1. 7 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку right +4. Платформа должна изменить угол отклонения сервопривода +5. Сервопривод на платформе повернулся вправо +6. Выполнен + +#### Поворот сервоприводов в плоскости xz + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку "up" +4. Платформа должна поднять сервопривод вверх +5. Сервопривод на платформе повернулся вверх +6. Выполнен + +#### Получение информации с датчиков линии. Белый лист + +1. 9 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 0 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков линии. Черный лист + +1. 10 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 1 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков расстояния + +1. 11 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Нажмите на кнопку "Sensors" +4. В приложении должно появится значение от 10 до 19 +5. В приложении появилось значение 21 напротив значения центрального датчика +6. Не выполнен \ No newline at end of file From 493a689911c2be1cd897b60544e046c6137fe8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B5=D0=B2?= Date: Wed, 13 Dec 2017 19:45:31 +0300 Subject: [PATCH 331/336] Delete tests.md --- documentation/tests.md | 149 ----------------------------------------- 1 file changed, 149 deletions(-) delete mode 100644 documentation/tests.md diff --git a/documentation/tests.md b/documentation/tests.md deleted file mode 100644 index 465058c..0000000 --- a/documentation/tests.md +++ /dev/null @@ -1,149 +0,0 @@ -# Проверка тестовых сценариев - -## Представление результатов - -Предоставление результатов требуется описать в следующем виде: - -1. Идентификатор -2. Назначение / название -3. Сценарий -4. Ожидаемый результат -5. Фактический результат (заполняется на этапе тестирования) -6. Оценка (заполняется на этапе тестирования) - -## Тестовые сценарии: - -#### Возможность подключения к платформе - -1. 1 -2. Возможность подключения к платформе -3. Произведите следующие шаги: - - 1. Включите платформу - - 2. Дождитесь загрузки платформы - - 3. Запустите приложение -4. В приложении появится надпись "Connected" -5. В приложении появилась надпись "Connected" -6. Выполнен - -#### Возможность принудительного отключения от платформы - -1. 2 -2. Возможность принудительного отключения от платформы по завершению работы с ней -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Нажать кнопку Exit в главном меню приложения - 3. Попробуйте заново подключиться к платформе -4. В приложении, появится надпись "Connected" -5. В приложении появилась надпись "Connected" -6. Выполнен - -#### Движение вперед - -1. 3 -2. Проверка движения платформы вперед -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "forward" -4. Платформа должна поехать вперед -5. Платформа поехала вперед -6. Выполнен - -#### Движение назад - -1. 4 -2. Проверка движения платформы назад -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "back" -4. Платформа должна поехать назад -5. Платформа поехала назад -6. Выполнен - -#### Разворот по направлению движения часовой стрелки - -1. 5 -2. Проверка возможности поворота платформы по часовой стрелке -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "right" -4. Платформа должна начать поворачиваться по часовой стрелке -5. Платформа начала поворачиваться по часовой стрелке -6. Выполнен - -#### Разворот против направления движения часовой стрелки - -1. 6 -2. Проверка возможности поворота платформы против часовой стрелки -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Motion" - 3. Выберите в приложении "left" -4. Платформа должна начать поворачиваться против часовой стрелки -5. Платформа начала поворачиваться против часовой стрелки -6. Выполнен - -#### Поворот сервоприводов в плоскости xy - -1. 7 -2. Проверка возможности поворота сервоприводов в плоскости xy -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Servo" - 3. Нажмите на кнопку right -4. Платформа должна изменить угол отклонения сервопривода -5. Сервопривод на платформе повернулся вправо -6. Выполнен - -#### Поворот сервоприводов в плоскости xz - -1. 8 -2. Проверка возможности поворота сервоприводов в плоскости xz -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Перейти из главного меню в меню "Servo" - 3. Нажмите на кнопку "up" -4. Платформа должна поднять сервопривод вверх -5. Сервопривод на платформе повернулся вверх -6. Выполнен - -#### Получение информации с датчиков линии. Белый лист - -1. 9 -2. Получение информации с датчиков линии. Проверка корректного определения белого цвета -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Положите под платформу лист белой бумаги - 3. Нажмите на кнопку "Sensors" -4. В приложении напротив нумерации датчиков линии должно появиться значение 0 -5. Были значения как 0, так и 1 -6. Не выполнен - -#### Получение информации с датчиков линии. Черный лист - -1. 10 -2. Получение информации с датчиков линии. Проверка корректного определения черного цвета -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Положите под платформу лист черной бумаги - 3. Нажмите на кнопку "Sensors" -4. В приложении напротив нумерации датчиков линии должно появиться значение 1 -5. Были значения как 0, так и 1 -6. Не выполнен - -#### Получение информации с датчиков расстояния - -1. 11 -2. Получение информации с датчиков расстояния -3. Произведите следующие шаги: - 1. Подключитесь к платформе - 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров - 3. Нажмите на кнопку "Sensors" -4. В приложении должно появится значение от 10 до 19 -5. В приложении появилось значение 21 напротив значения центрального датчика -6. Не выполнен \ No newline at end of file From edb1c15013e3d4c6864c592e5c4ff35d51773f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B5=D0=B2?= Date: Wed, 13 Dec 2017 19:46:01 +0300 Subject: [PATCH 332/336] Add files via upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit новые тесты --- documentation/tests.md | 171 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 documentation/tests.md diff --git a/documentation/tests.md b/documentation/tests.md new file mode 100644 index 0000000..df1783d --- /dev/null +++ b/documentation/tests.md @@ -0,0 +1,171 @@ +# Проверка тестовых сценариев + +## Представление результатов + +Предоставление результатов требуется описать в следующем виде: + +1. Идентификатор +2. Назначение / название +3. Сценарий +4. Ожидаемый результат +5. Фактический результат (заполняется на этапе тестирования) +6. Оценка (заполняется на этапе тестирования) + +## Тестовые сценарии: + +#### Возможность подключения к платформе + +1. 1 +2. Возможность подключения к платформе +3. Произведите следующие шаги: + + 1. Включите платформу + + 2. Дождитесь загрузки платформы + + 3. Запустите приложение +4. В приложении появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Возможность принудительного отключения от платформы + +1. 2 +2. Возможность принудительного отключения от платформы по завершению работы с ней +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Нажать кнопку Exit в главном меню приложения + 3. Попробуйте заново подключиться к платформе +4. В приложении, появится надпись "Connected" +5. В приложении появилась надпись "Connected" +6. Выполнен + +#### Движение вперед + +1. 3 +2. Проверка движения платформы вперед +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "forward" +4. Платформа должна поехать вперед +5. Платформа поехала вперед +6. Выполнен + +#### Движение назад + +1. 4 +2. Проверка движения платформы назад +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "back" +4. Платформа должна поехать назад +5. Платформа поехала назад +6. Выполнен + +#### Разворот по направлению движения часовой стрелки + +1. 5 +2. Проверка возможности поворота платформы по часовой стрелке +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "right" +4. Платформа должна начать поворачиваться по часовой стрелке +5. Платформа начала поворачиваться по часовой стрелке +6. Выполнен + +#### Разворот против направления движения часовой стрелки + +1. 6 +2. Проверка возможности поворота платформы против часовой стрелки +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Motion" + 3. Выберите в приложении "left" +4. Платформа должна начать поворачиваться против часовой стрелки +5. Платформа начала поворачиваться против часовой стрелки +6. Выполнен + +#### Поворот сервоприводов в плоскости xy + +1. 7 +2. Проверка возможности поворота сервоприводов в плоскости xy +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку right +4. Платформа должна изменить угол отклонения сервопривода +5. Сервопривод на платформе повернулся вправо +6. Выполнен + +#### Поворот сервоприводов в плоскости xz + +1. 8 +2. Проверка возможности поворота сервоприводов в плоскости xz +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Перейти из главного меню в меню "Servo" + 3. Нажмите на кнопку "up" +4. Платформа должна поднять сервопривод вверх +5. Сервопривод на платформе повернулся вверх +6. Выполнен + +#### Получение информации с датчиков линии. Белый лист + +1. 9 +2. Получение информации с датчиков линии. Проверка корректного определения белого цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист белой бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 0 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков линии. Черный лист + +1. 10 +2. Получение информации с датчиков линии. Проверка корректного определения черного цвета +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Положите под платформу лист черной бумаги + 3. Нажмите на кнопку "Sensors" +4. В приложении напротив нумерации датчиков линии должно появиться значение 1 +5. Были значения как 0, так и 1 +6. Не выполнен + +#### Получение информации с датчиков расстояния + +1. 11 +2. Получение информации с датчиков расстояния +3. Произведите следующие шаги: + 1. Подключитесь к платформе + 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров + 3. Нажмите на кнопку "Sensors" +4. В приложении должно появится значение от 10 до 19 +5. В приложении появилось значение 21 напротив значения центрального датчика +6. Не выполнен + +#### Смена языка + +1. 12 +2. Смена языка интерфеса +3. Произведите следующие шаги: + 1. Нажмите на кнопку "Settings" в главном меню + 2. Измените язык +4. В приложении должен измениться язык интерфейса +5. В приложении измелися интерфейс +6. Выполнен + +#### Выбор другого API + +1. 13 +2. Смена API +3. Произведите следующие шани: + 1. Нажмите на кнопку "Settings" в главном меню + 2. Выберите дргой API +4. Приложение должно продолжать работу, все команды пользователя должны выполняться +5. Свзясь с платформой прервалась +6. Не выполнен \ No newline at end of file From 3d6d8fe01f5adf5341297135a377acca6e042701 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 13 Dec 2017 20:22:54 +0300 Subject: [PATCH 333/336] Some typos were fixed. Test cases & conclusion were added --- documentation/test_cases.md | 40 ++++++++++++++++++++++++++++++++++++- documentation/test_plan.md | 6 +++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/documentation/test_cases.md b/documentation/test_cases.md index 465058c..ecdcf48 100644 --- a/documentation/test_cases.md +++ b/documentation/test_cases.md @@ -146,4 +146,42 @@ 3. Нажмите на кнопку "Sensors" 4. В приложении должно появится значение от 10 до 19 5. В приложении появилось значение 21 напротив значения центрального датчика -6. Не выполнен \ No newline at end of file +6. Не выполнен + +#### Смена языка + +1. 12 +2. Смена языка интерфеса +3. Произведите следующие шаги: + 1. Нажмите на кнопку "Settings" в главном меню + 2. Измените язык +4. В приложении должен измениться язык интерфейса +5. Язык изменился +6. Выполнен + +#### Выбор другого API + +1. 13 +2. Смена API +3. Произведите следующие шаги: + 1. Нажмите на кнопку "Settings" в главном меню + 2. Выберите другой API +4. Приложение должно продолжать работу, все команды пользователя должны выполняться +5. Приложение аварийно завершает свою работу +6. Не выполнен + +### Выводы + +Выполняются пункты: 1-8, 12. + +| Функциональные требования | ID теста | Успешность прохождения тестов, % | +| ---------------------------------------- | :------: | :------------------------------: | +| Поддержка беспроводной связи с платформой через Bluetooth | 1-2 | 100 | +| Получение и вывод информации с датчиков линии | 9-10 | 0 | +| Получение и вывод информации с датчиков расстояни | 11 | 0 | +| Управление гусеницами платформы | 3-6 | 100 | +| Управление сервоприводами платформы | 7-8 | 100 | +| Выбор языка (русского или английского) | 12 | 100 | +| Выбор нескольких версии API для взаимодействия с платформой | 13 | 0 | + +Видно, что часть требований не выполняется вовсе. Например, не работает получение информации с датчиков и взаимодействие с несколькими версиями API. diff --git a/documentation/test_plan.md b/documentation/test_plan.md index fa5586b..aff6314 100644 --- a/documentation/test_plan.md +++ b/documentation/test_plan.md @@ -195,14 +195,14 @@ 1. 13 2. Смена API -3. Произведите следующие шани: +3. Произведите следующие шаги: 1. Нажмите на кнопку "Settings" в главном меню - 2. Выберите дргой API + 2. Выберите другой API 4. Приложение должно продолжать работу, все команды пользователя должны выполняться ### Вывод -Данные тесты показывают выполенние функциональных требований. Соответсвите функциональных требований и тестов: +Данные тесты показывают выполнение функциональных требований. Соответствие функциональных требований и тестов: | Функциональные требования | ID теста | | ---------------------------------------- | :------: | From 3cfdc86a4e826cc3bd5d1d8e6fc571876a2adc86 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Wed, 13 Dec 2017 10:57:58 +0300 Subject: [PATCH 334/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B,=20?= =?UTF-8?q?=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D0=B1=D1=8B=D0=BB?= =?UTF-8?q?=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B9=D0=B4=D0=B5=D0=BD=D1=8B=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BD=D0=BE=D0=BC=20=D0=BA=D0=BB=D0=B8=D0=BD=D1=82-?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/TestCases.md | 51 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/docs/TestCases.md b/docs/TestCases.md index c59ad2d..a7c4425 100644 --- a/docs/TestCases.md +++ b/docs/TestCases.md @@ -97,8 +97,8 @@ 1. Подключитесь к платформе 2. Выберите в приложении "set horisontal servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) 4. Платформа должна установить сервоприводы на указанный угол -5. Нет такого функцианала -6. Не прошел +5. Сервопривод был установлен на указанные угол xy +6. Прошел #### Поворот сервоприводов в плоскости xz @@ -108,8 +108,8 @@ 1. Подключитесь к платформе 2. Выберите в приложении "set vertical servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) 4. Платформа должна установить сервоприводы на указанный угол -5. Нет такого функцианала -6. Не прошел +5. Сервопривод был установлен на указанный угол в плоскости xz +6. Прошел #### Получение текущего угла отклонения в сервоприводов в плоскости xy @@ -120,8 +120,8 @@ 2. Выберите в приложении "set horisontal servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) 3. Выберите в приложении "get horisontal servo angle in degree" 4. В приложении должно появится значение, которое было введено в пункте 3.2 -5. Нет такого функцианала -6. Не прошел +5. На экрне появился угол отклонения сервопривода в плоскости xy +6. Прошел #### Получение текущего угла отклонения в сервоприводов в плоскости xz @@ -132,8 +132,8 @@ 2. Выберите в приложении "set vertical servo angle in degree". Укажите корректный угол в градусах (от 0 до 180) 3. Выберите в приложении "get vertical servo angle in degree" 4. В приложении должно появится значение, которое было введено в пункте 3.2 -5. Нет такого функцианала -6. Не прошел +5. На экрне появился угол отклонения сервопривода в плоскости xz +6. Прошел #### Некорректный поворот сервоприводов в плоскости xy @@ -143,8 +143,8 @@ 1. Подключитесь к платформе 2. Выберите в приложении "set horisontal servo angle in degree". Укажите некорректный угол в градусах (больше 180) 4. Платформа не должна изменить текущий угол сервоприводов -5. Нет такого функцианала -6. Не прошел +5. Положение сервопривода не изменилось +6. Прошел #### Некорректный поворот сервоприводов в плоскости xz @@ -154,8 +154,8 @@ 1. Подключитесь к платформе 2. Выберите в приложении "set vertical servo angle in degree". Укажите некорректный угол в градусах (больше 180) 4. Платформа не должна изменить текущий угол сервоприводов -5. Нет такого функцианала -6. Не прошел +5. Положение сервопривода не изменилось +6. Прошел #### Получение информации с датчиков линии. Белый лист @@ -166,8 +166,8 @@ 2. Положите под платформу лист белой бумаги 3. Выберите в приложении "get fixed line value". Укажите номер датчика в диапазоне от 1 до 5 4. В приложении должно появится 0 -5. Информация с датчиков была получена -6. Прошел +5. У одного из датчиков появилось значение 1 +6. Не прошел #### Получение информации с датчиков линии. Черный лист @@ -178,7 +178,7 @@ 2. Положите под платформу лист черной бумаги 3. Выберите в приложении "get fixed line value". Укажите номер датчика в диапазоне от 1 до 5 4. В приложении должно появится 1 -5. Нет такого функцианала +5. У одного из датчиков появилось значение 0 6. Не прошел #### Получение информации с датчиков расстояния @@ -190,8 +190,8 @@ 2. Подставьте перед центральным датчиком расстояния какой-нибудь непрозрачный предмет, например книгу, на расстоянии приблизительно 15 сантиметров 3. Выберите в приложении "get fixed distance value". Укажите номер датчика 3 4. В приложении должно появится значение от 10 до 19 -5. Информация с датчиков была получена -6. Прошел +5. Были получены значения 21 и более +6. Не прошел #### Проверка времени жизни от батареи @@ -218,17 +218,18 @@ ### Выводы -Выполняются пункты: 1-7, 14, 16, 17, 18. +Пункты 14-16 не прошли. + | Атрибут качества | Результат(в %) | | ------------------------------ | -------------- | -| Функциональная полнота | 56 | -| Функциональная корректность | 56 | -| Временная характеристика | 61 | -| Доступность | 59 | -| Защита от ошибок пользователей | 0 | +| Функциональная полнота | 81 | +| Функциональная корректность | 81 | +| Временная характеристика | 100 | +| Доступность | 100 | +| Защита от ошибок пользователей | 100 | | Модульность | - | | Устанавливаемость | - | -| Заменяемость | 56 | +| Заменяемость | 81 | -Видно, что продукт не обладает защитой от ошибок пользователя. \ No newline at end of file +Видно, что из-за проблем с датчиками линии и расстояния продукт не обладает следующеми атрибутами качества: функциональная полнота, функциональная корректность, заменяемость. \ No newline at end of file From c910e36592de043328281b132b5cf5da50853050 Mon Sep 17 00:00:00 2001 From: AJIOB Date: Wed, 10 Jan 2018 00:51:51 +0300 Subject: [PATCH 335/336] Moving arduino docs to special folder --- docs/{ => Arduino api v4}/Diagrams/Classes.png | Bin .../Diagrams/Components&Deployment.png | Bin .../Diagrams/ConnectToPlatformActivity.png | Bin .../Diagrams/ConnectToPlatformSequence.png | Bin .../Diagrams/GetLineInfoActivity.png | Bin .../Diagrams/GetLineInfoSequence.png | Bin .../Diagrams/GetMessageActivity.png | Bin .../Diagrams/GetMessageSequence.png | Bin docs/{ => Arduino api v4}/Diagrams/mainStates.png | Bin docs/{ => Arduino api v4}/Diagrams/useCases.png | Bin docs/{ => Arduino api v4}/FlowOfEvents.md | 0 docs/{ => Arduino api v4}/Glossary.md | 0 docs/{ => Arduino api v4}/Requirements.md | 0 docs/{ => Arduino api v4}/TestCases.md | 0 docs/{ => Arduino api v4}/TestPlan.md | 0 .../TestPlan_images/mega_sensor_shield_loaded.jpg | Bin 16 files changed, 0 insertions(+), 0 deletions(-) rename docs/{ => Arduino api v4}/Diagrams/Classes.png (100%) rename docs/{ => Arduino api v4}/Diagrams/Components&Deployment.png (100%) rename docs/{ => Arduino api v4}/Diagrams/ConnectToPlatformActivity.png (100%) rename docs/{ => Arduino api v4}/Diagrams/ConnectToPlatformSequence.png (100%) rename docs/{ => Arduino api v4}/Diagrams/GetLineInfoActivity.png (100%) rename docs/{ => Arduino api v4}/Diagrams/GetLineInfoSequence.png (100%) rename docs/{ => Arduino api v4}/Diagrams/GetMessageActivity.png (100%) rename docs/{ => Arduino api v4}/Diagrams/GetMessageSequence.png (100%) rename docs/{ => Arduino api v4}/Diagrams/mainStates.png (100%) rename docs/{ => Arduino api v4}/Diagrams/useCases.png (100%) rename docs/{ => Arduino api v4}/FlowOfEvents.md (100%) rename docs/{ => Arduino api v4}/Glossary.md (100%) rename docs/{ => Arduino api v4}/Requirements.md (100%) rename docs/{ => Arduino api v4}/TestCases.md (100%) rename docs/{ => Arduino api v4}/TestPlan.md (100%) rename docs/{ => Arduino api v4}/TestPlan_images/mega_sensor_shield_loaded.jpg (100%) diff --git a/docs/Diagrams/Classes.png b/docs/Arduino api v4/Diagrams/Classes.png similarity index 100% rename from docs/Diagrams/Classes.png rename to docs/Arduino api v4/Diagrams/Classes.png diff --git a/docs/Diagrams/Components&Deployment.png b/docs/Arduino api v4/Diagrams/Components&Deployment.png similarity index 100% rename from docs/Diagrams/Components&Deployment.png rename to docs/Arduino api v4/Diagrams/Components&Deployment.png diff --git a/docs/Diagrams/ConnectToPlatformActivity.png b/docs/Arduino api v4/Diagrams/ConnectToPlatformActivity.png similarity index 100% rename from docs/Diagrams/ConnectToPlatformActivity.png rename to docs/Arduino api v4/Diagrams/ConnectToPlatformActivity.png diff --git a/docs/Diagrams/ConnectToPlatformSequence.png b/docs/Arduino api v4/Diagrams/ConnectToPlatformSequence.png similarity index 100% rename from docs/Diagrams/ConnectToPlatformSequence.png rename to docs/Arduino api v4/Diagrams/ConnectToPlatformSequence.png diff --git a/docs/Diagrams/GetLineInfoActivity.png b/docs/Arduino api v4/Diagrams/GetLineInfoActivity.png similarity index 100% rename from docs/Diagrams/GetLineInfoActivity.png rename to docs/Arduino api v4/Diagrams/GetLineInfoActivity.png diff --git a/docs/Diagrams/GetLineInfoSequence.png b/docs/Arduino api v4/Diagrams/GetLineInfoSequence.png similarity index 100% rename from docs/Diagrams/GetLineInfoSequence.png rename to docs/Arduino api v4/Diagrams/GetLineInfoSequence.png diff --git a/docs/Diagrams/GetMessageActivity.png b/docs/Arduino api v4/Diagrams/GetMessageActivity.png similarity index 100% rename from docs/Diagrams/GetMessageActivity.png rename to docs/Arduino api v4/Diagrams/GetMessageActivity.png diff --git a/docs/Diagrams/GetMessageSequence.png b/docs/Arduino api v4/Diagrams/GetMessageSequence.png similarity index 100% rename from docs/Diagrams/GetMessageSequence.png rename to docs/Arduino api v4/Diagrams/GetMessageSequence.png diff --git a/docs/Diagrams/mainStates.png b/docs/Arduino api v4/Diagrams/mainStates.png similarity index 100% rename from docs/Diagrams/mainStates.png rename to docs/Arduino api v4/Diagrams/mainStates.png diff --git a/docs/Diagrams/useCases.png b/docs/Arduino api v4/Diagrams/useCases.png similarity index 100% rename from docs/Diagrams/useCases.png rename to docs/Arduino api v4/Diagrams/useCases.png diff --git a/docs/FlowOfEvents.md b/docs/Arduino api v4/FlowOfEvents.md similarity index 100% rename from docs/FlowOfEvents.md rename to docs/Arduino api v4/FlowOfEvents.md diff --git a/docs/Glossary.md b/docs/Arduino api v4/Glossary.md similarity index 100% rename from docs/Glossary.md rename to docs/Arduino api v4/Glossary.md diff --git a/docs/Requirements.md b/docs/Arduino api v4/Requirements.md similarity index 100% rename from docs/Requirements.md rename to docs/Arduino api v4/Requirements.md diff --git a/docs/TestCases.md b/docs/Arduino api v4/TestCases.md similarity index 100% rename from docs/TestCases.md rename to docs/Arduino api v4/TestCases.md diff --git a/docs/TestPlan.md b/docs/Arduino api v4/TestPlan.md similarity index 100% rename from docs/TestPlan.md rename to docs/Arduino api v4/TestPlan.md diff --git a/docs/TestPlan_images/mega_sensor_shield_loaded.jpg b/docs/Arduino api v4/TestPlan_images/mega_sensor_shield_loaded.jpg similarity index 100% rename from docs/TestPlan_images/mega_sensor_shield_loaded.jpg rename to docs/Arduino api v4/TestPlan_images/mega_sensor_shield_loaded.jpg From 85d86a8ff88f34edc7ae4d8a6dab1c4d81c36fd3 Mon Sep 17 00:00:00 2001 From: Kimentii Date: Sat, 13 Jan 2018 12:36:38 +0300 Subject: [PATCH 336/336] =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=88=D0=B8=D1=80?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20gitignore.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Java/Mobile/Application2.0/.gitignore | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/code/Java/Mobile/Application2.0/.gitignore b/code/Java/Mobile/Application2.0/.gitignore index 39fb081..bd1302f 100644 --- a/code/Java/Mobile/Application2.0/.gitignore +++ b/code/Java/Mobile/Application2.0/.gitignore @@ -1,9 +1,18 @@ *.iml -.gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store -/build /captures .externalNativeBuild +*.log + +# Gradle files +.gradle/ +build/ + +# Generated files +bin/ +gen/ +out/ +

|CPD{06{N8L9)n| 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 literal 0 HcmV?d00001 diff --git a/documentation/user_interface/settings_activity.png b/documentation/user_interface/settings_activity.png new file mode 100644 index 0000000000000000000000000000000000000000..68b23ebac5bac7531de291fd160732560de0e705 GIT binary patch literal 17433 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 Date: Tue, 10 Oct 2017 12:20:56 +0300 Subject: [PATCH 151/336] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=80=D1=82=D0=B8=D0=BD=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- documentation/requirement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/requirement.md b/documentation/requirement.md index 60d257b..e3d55ff 100644 --- a/documentation/requirement.md +++ b/documentation/requirement.md @@ -53,7 +53,7 @@ Только после этого настоятельно рекомендуется посылать следующую команду. ### Интерфес пользователя -![](//user_interface/main_menu.png) +![](user_interface/main_menu.png) ### Характреристики пользователей Данное приложение предназначено для пользователей имеющих базовые знания операционной системы Android. Пользователь должен уметь включать и отключать Bluetooth на своем устройстве, а также уметь подключиться From 25c1cb558bb9575849122fe810f8ff62b6838cba Mon Sep 17 00:00:00 2001 From: Kimentii Date: Tue, 10 Oct 2017 21:56:14 +0300 Subject: [PATCH 152/336] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D0=BA=D0=B8=D0=B9=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Mobile/Application2.0/app/build.gradle | 6 +- .../app/src/main/AndroidManifest.xml | 19 +- .../kimentii/application20/MainActivity.java | 50 +++++ .../application20/MotionActivity.java | 18 ++ .../application20/SensorsActivity.java | 17 ++ .../kimentii/application20/ServoActivity.java | 18 ++ .../application20/SettingsActivity.java | 18 ++ .../app/src/main/res/layout/activity_main.xml | 44 ++++- .../src/main/res/layout/activity_motion.xml | 72 +++++++ .../src/main/res/layout/activity_sensors.xml | 186 ++++++++++++++++++ .../src/main/res/layout/activity_servo.xml | 68 +++++++ .../src/main/res/layout/activity_settings.xml | 60 ++++++ .../app/src/main/res/values/strings.xml | 14 ++ documentation/requirement.md | 4 + 14 files changed, 581 insertions(+), 13 deletions(-) create mode 100644 code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MotionActivity.java create mode 100644 code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SensorsActivity.java create mode 100644 code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/ServoActivity.java create mode 100644 code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SettingsActivity.java create mode 100644 code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_motion.xml create mode 100644 code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_sensors.xml create mode 100644 code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_servo.xml create mode 100644 code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_settings.xml diff --git a/code/Java/Mobile/Application2.0/app/build.gradle b/code/Java/Mobile/Application2.0/app/build.gradle index d378d45..f5e5826 100644 --- a/code/Java/Mobile/Application2.0/app/build.gradle +++ b/code/Java/Mobile/Application2.0/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "com.example.kimentii.application20" minSdkVersion 17 - targetSdkVersion 25 + targetSdkVersion 17 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -17,10 +17,12 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + productFlavors { + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) diff --git a/code/Java/Mobile/Application2.0/app/src/main/AndroidManifest.xml b/code/Java/Mobile/Application2.0/app/src/main/AndroidManifest.xml index a455d3d..879e131 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/AndroidManifest.xml +++ b/code/Java/Mobile/Application2.0/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.example.kimentii.application20"> - + - + + + + + + \ No newline at end of file diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MainActivity.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MainActivity.java index a1b6a1b..437f821 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MainActivity.java +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MainActivity.java @@ -1,13 +1,63 @@ package com.example.kimentii.application20; +import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.view.Menu; +import android.view.View; +import android.widget.Button; public class MainActivity extends AppCompatActivity { + private Button motionButton; + private Button servoButton; + private Button sensorsButton; + private Button settingsButton; + private Button exitButton; + + class Listener implements View.OnClickListener { + Intent intent; + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.motion_button: + intent = new Intent(getApplicationContext(), MotionActivity.class); + startActivity(intent); + break; + case R.id.servo_button: + intent = new Intent(getApplicationContext(), ServoActivity.class); + startActivity(intent); + break; + case R.id.sensors_button: + intent = new Intent(getApplicationContext(), SensorsActivity.class); + startActivity(intent); + break; + case R.id.settings_button: + intent = new Intent(getApplicationContext(), SettingsActivity.class); + startActivity(intent); + break; + case R.id.exit_button: + break; + } + } + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + Listener listener = new Listener(); + motionButton = (Button) findViewById(R.id.motion_button); + servoButton = (Button) findViewById(R.id.servo_button); + sensorsButton = (Button) findViewById(R.id.sensors_button); + settingsButton = (Button) findViewById(R.id.settings_button); + exitButton = (Button) findViewById(R.id.exit_button); + motionButton.setOnClickListener(listener); + servoButton.setOnClickListener(listener); + sensorsButton.setOnClickListener(listener); + settingsButton.setOnClickListener(listener); + exitButton.setOnClickListener(listener); } + } diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MotionActivity.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MotionActivity.java new file mode 100644 index 0000000..661bf2b --- /dev/null +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/MotionActivity.java @@ -0,0 +1,18 @@ +package com.example.kimentii.application20; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; + +public class MotionActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_motion); + ActionBar actionBar = getSupportActionBar(); + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } +} diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SensorsActivity.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SensorsActivity.java new file mode 100644 index 0000000..6a787a4 --- /dev/null +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SensorsActivity.java @@ -0,0 +1,17 @@ +package com.example.kimentii.application20; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; + +public class SensorsActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sensors); + ActionBar actionBar = getSupportActionBar(); + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } +} diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/ServoActivity.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/ServoActivity.java new file mode 100644 index 0000000..6903d96 --- /dev/null +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/ServoActivity.java @@ -0,0 +1,18 @@ +package com.example.kimentii.application20; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; + +public class ServoActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_servo); + ActionBar actionBar = getSupportActionBar(); + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } +} diff --git a/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SettingsActivity.java b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SettingsActivity.java new file mode 100644 index 0000000..13a7ac4 --- /dev/null +++ b/code/Java/Mobile/Application2.0/app/src/main/java/com/example/kimentii/application20/SettingsActivity.java @@ -0,0 +1,18 @@ +package com.example.kimentii.application20; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; + +public class SettingsActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settings); + ActionBar actionBar = getSupportActionBar(); + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } +} diff --git a/code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_main.xml b/code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_main.xml index 8857467..a50b2a6 100644 --- a/code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_main.xml +++ b/code/Java/Mobile/Application2.0/app/src/main/res/layout/activity_main.xml @@ -1,18 +1,46 @@ - - + android:orientation="vertical" + android:layout_centerVertical="true" + android:layout_centerHorizontal="true"> - + + public partial class MainWindow : Window { + private readonly MainWindowViewModel _vm; + public MainWindow() { InitializeComponent(); + _vm = DataContext as MainWindowViewModel; + } + + private void OnConnectClicked(object sender, RoutedEventArgs e) + { + if (!_vm.ToggleConnection()) + { + MessageBox.Show("Cannot connect or disconnect from device"); + } } } } diff --git a/code/c#/Sample App/MainWindowViewModel.cs b/code/c#/Sample App/MainWindowViewModel.cs index 43beb2d..f7e815c 100644 --- a/code/c#/Sample App/MainWindowViewModel.cs +++ b/code/c#/Sample App/MainWindowViewModel.cs @@ -1,4 +1,6 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; +using System.Windows; namespace Sample_App { @@ -40,13 +42,87 @@ protected virtual void OnPropertyChanged(string propertyName) #endregion + private bool _maskIsConnected = false; + private const int DinstanseNum = 5; private const int LineNum = 5; + private const int LineWhite = 0; public uint[] Distanse { get; } = new uint[DinstanseNum]; ///