refactor(comframe): move common definitions and implement serial port functions
- Move common definitions from defines.h to comframe.h - Implement get_com_tty_id and init_tty functions in comframe.cpp - Update extern_interface to use pthreads and inicpp - Simplify event handling in event.cpp - Remove unused includes and cleanup code in various files
This commit is contained in:
parent
4669644cce
commit
a2f04fb3cb
|
@ -0,0 +1,63 @@
|
||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
project(extern_interface CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
if (NOT CMAKE_CROSSCOMPILING)
|
||||||
|
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
set(CMAKE_CXX_FLAGS "-std=c++17 -fPIC -Wall ${CMAKE_CXX_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-g ${CMAKE_CXX_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-g -O2 ${CMAKE_CXX_FLAGS}")
|
||||||
|
elseif (WIN32)
|
||||||
|
# windows platform
|
||||||
|
#add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
|
||||||
|
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /EHsc")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /EHsc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_CROSSCOMPILING)
|
||||||
|
message(STATUS "Cross compiling ...")
|
||||||
|
message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
|
||||||
|
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(./include)
|
||||||
|
|
||||||
|
aux_source_directory(./src SRC_LIST)
|
||||||
|
|
||||||
|
add_library(extern_interface_static STATIC ${SRC_LIST})
|
||||||
|
add_library(extern_interface SHARED ${SRC_LIST})
|
||||||
|
|
||||||
|
# 设置测试文件和公共源文件
|
||||||
|
set(TESTS_DIR "${CMAKE_SOURCE_DIR}/tests")
|
||||||
|
set(TEST_COMMON_SOURCE "${TESTS_DIR}/c_testcase.cpp")
|
||||||
|
|
||||||
|
# 查找所有以 test_ 开头的文件
|
||||||
|
file(GLOB_RECURSE TEST_FILES "${TESTS_DIR}/test_*.cpp")
|
||||||
|
|
||||||
|
# 循环遍历每个测试文件并创建可执行文件
|
||||||
|
foreach(TEST_FILE ${TEST_FILES})
|
||||||
|
# 获取文件名(不带路径和扩展名)
|
||||||
|
get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)
|
||||||
|
|
||||||
|
# 创建可执行文件
|
||||||
|
add_executable(${TEST_NAME} ${TEST_FILE} ${TEST_COMMON_SOURCE} ${SRC_LIST})
|
||||||
|
|
||||||
|
# 将可执行文件路径添加到列表中
|
||||||
|
list(APPEND TEST_EXECUTABLES "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
add_test(NAME test
|
||||||
|
COMMAND ${CMAKE_SOURCE_DIR}/scripts/unittest.py ${TEST_EXECUTABLES}
|
||||||
|
)
|
|
@ -6,9 +6,30 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "defines.h"
|
|
||||||
//#define COM_FRAME_DEBUG
|
//#define COM_FRAME_DEBUG
|
||||||
|
|
||||||
|
#define COM_FRAME_MAGIC_NUMBER 0xEB90
|
||||||
|
#define COM_FRAME_DEFAULT_PAYLOAD_LENGTH 2
|
||||||
|
#define COM_FRAME_PADDING_DATA 0xAA
|
||||||
|
|
||||||
|
#define COM_FRAME_TYPE_COMMAND 0x00C0
|
||||||
|
#define COM_FRAME_TYPE_SPEECH_INJECTED 0x00D0
|
||||||
|
#define COM_FRAME_TYPE_SPEECH_TEXT 0x00D0
|
||||||
|
#define COM_FRAME_TYPE_SPEECH_PCM 0x00D1
|
||||||
|
#define COM_FRAME_TYPE_AUDIO 0x00D1
|
||||||
|
#define COM_FRAME_TYPE_REQUEST 0x0090
|
||||||
|
#define COM_FRAME_TYPE_TELEMETRY_REQUEST 0x00B0
|
||||||
|
#define COM_FRAME_TYPE_TELEMETRY_ANSWER 0x0070
|
||||||
|
#define COM_FRAME_TYPE_TELEMETRY_ERROR 0x0071
|
||||||
|
|
||||||
|
#define COM_FRAME_ADDRESS_VOIX 0x011A
|
||||||
|
|
||||||
|
// added by gejp start 2024.10.03
|
||||||
|
#define COM_FRAME_TYPE_GRANT_TIME 0x0085
|
||||||
|
#define COM_FRAME_TYPE_VOICE_ANNOUNCEMENT_AND_ALARM_CODE_REQUEST 0x0083
|
||||||
|
#define COM_FRAME_TYPE_VOICE_ANNOUNCEMENT_AND_ALARM_CODE_RESPONSE 0x0083
|
||||||
|
|
||||||
#define byteswapl(x) (0xff000000 & x << 24) \
|
#define byteswapl(x) (0xff000000 & x << 24) \
|
||||||
|(0x00ff0000 & x << 8) \
|
|(0x00ff0000 & x << 8) \
|
||||||
|(0x0000ff00 & x >> 8) \
|
|(0x0000ff00 & x >> 8) \
|
||||||
|
@ -230,8 +251,8 @@ ComFrame* ComFrame_Receive(int tty_id, const size_t buffer_size, const bool swap
|
||||||
/// @return frame (little endian) in buffer or NULL
|
/// @return frame (little endian) in buffer or NULL
|
||||||
ComFrame* ComFrame_ReceiveEx(int tty_id, void* buffer, const size_t buffer_size, size_t* p_offset, size_t* p_cached_size, bool* p_run_flag, const bool swap_endian);
|
ComFrame* ComFrame_ReceiveEx(int tty_id, void* buffer, const size_t buffer_size, size_t* p_offset, size_t* p_cached_size, bool* p_run_flag, const bool swap_endian);
|
||||||
|
|
||||||
//int get_com_tty_id(const char* path, unsigned int baudRate);
|
int get_com_tty_id(const char* path, unsigned int baudRate);
|
||||||
//void init_tty(int tty_id, unsigned int baudRate);
|
void init_tty(int tty_id, unsigned int baudRate);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "CCfgFileParser.h"
|
|
||||||
#include "dataqueue.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
#define PrintFilePos() //printf("\nfile:%s, line:%2d---",__FILE__,__LINE__);
|
#define PrintFilePos() //printf("\nfile:%s, line:%2d---",__FILE__,__LINE__);
|
||||||
|
@ -33,26 +30,7 @@ using namespace std;
|
||||||
|
|
||||||
|
|
||||||
//-------------------host telemetry defines start --------------------------
|
//-------------------host telemetry defines start --------------------------
|
||||||
#define COM_FRAME_MAGIC_NUMBER 0xEB90
|
|
||||||
#define COM_FRAME_DEFAULT_PAYLOAD_LENGTH 2
|
|
||||||
#define COM_FRAME_PADDING_DATA 0xAA
|
|
||||||
|
|
||||||
#define COM_FRAME_TYPE_COMMAND 0x00C0
|
|
||||||
#define COM_FRAME_TYPE_SPEECH_INJECTED 0x00D0
|
|
||||||
#define COM_FRAME_TYPE_SPEECH_TEXT 0x00D0
|
|
||||||
#define COM_FRAME_TYPE_SPEECH_PCM 0x00D1
|
|
||||||
#define COM_FRAME_TYPE_AUDIO 0x00D1
|
|
||||||
#define COM_FRAME_TYPE_REQUEST 0x0090
|
|
||||||
#define COM_FRAME_TYPE_TELEMETRY_REQUEST 0x00B0
|
|
||||||
#define COM_FRAME_TYPE_TELEMETRY_ANSWER 0x0070
|
|
||||||
#define COM_FRAME_TYPE_TELEMETRY_ERROR 0x0071
|
|
||||||
|
|
||||||
#define COM_FRAME_ADDRESS_VOIX 0x011A
|
|
||||||
|
|
||||||
// added by gejp start 2024.10.03
|
|
||||||
#define COM_FRAME_TYPE_GRANT_TIME 0x0085
|
|
||||||
#define COM_FRAME_TYPE_VOICE_ANNOUNCEMENT_AND_ALARM_CODE_REQUEST 0x0083
|
|
||||||
#define COM_FRAME_TYPE_VOICE_ANNOUNCEMENT_AND_ALARM_CODE_RESPONSE 0x0083
|
|
||||||
|
|
||||||
|
|
||||||
#define CMD_CODE_TELEMETRY_LOW_CABIN_TEMPERATURE 0x2F01
|
#define CMD_CODE_TELEMETRY_LOW_CABIN_TEMPERATURE 0x2F01
|
||||||
|
|
|
@ -46,7 +46,7 @@ union PacketData
|
||||||
typedef void (*et_callback_t)(uint32_t, size_t, union PacketData);
|
typedef void (*et_callback_t)(uint32_t, size_t, union PacketData);
|
||||||
|
|
||||||
EXTERN_INTERFACE_PUBLIC
|
EXTERN_INTERFACE_PUBLIC
|
||||||
void extern_interface_init(const char* config_path, et_callback_t cb);
|
int extern_interface_init(const char* config_path, et_callback_t cb);
|
||||||
EXTERN_INTERFACE_PUBLIC
|
EXTERN_INTERFACE_PUBLIC
|
||||||
void extern_interface_send(uint32_t type, size_t len, union PacketData data);
|
void extern_interface_send(uint32_t type, size_t len, union PacketData data);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,687 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 dujingning <djn2019x@163.com> <https://github.com/dujingning/inicpp.git>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __JN_INICPP_H__
|
||||||
|
#define __JN_INICPP_H__
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// for std::string <==> std::wstring convert
|
||||||
|
#include <codecvt>
|
||||||
|
#include <locale>
|
||||||
|
|
||||||
|
#ifdef INICPP_DEBUG
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class TimeFormatter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string format(const std::string &format = "%Y-%m-%d %H:%M:%S")
|
||||||
|
{
|
||||||
|
std::time_t t = std::time(nullptr);
|
||||||
|
std::tm tm = *std::localtime(&t);
|
||||||
|
std::array<char, 100> buffer;
|
||||||
|
std::strftime(buffer.data(), buffer.size(), format.c_str(), &tm);
|
||||||
|
return buffer.data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CODE_INFO std::string(" | Code:\'file:") + std::string(__FILE__) + ",function:" + std::string(__FUNCTION__) + ",line:" + std::to_string(__LINE__) + '\''
|
||||||
|
#define INI_DEBUG(x) std::cout << "INICPP " << TimeFormatter::format() << " : " << x << CODE_INFO << std::endl
|
||||||
|
|
||||||
|
#else // #ifdef INICPP_DEBUG
|
||||||
|
#define INI_DEBUG(x)
|
||||||
|
#endif // #ifdef INICPP_DEBUG
|
||||||
|
|
||||||
|
namespace inicpp
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef struct KeyValueNode
|
||||||
|
{
|
||||||
|
std::string Value = "";
|
||||||
|
int lineNumber = -1; // text line start with 1
|
||||||
|
} KeyValueNode;
|
||||||
|
|
||||||
|
class section
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
section() : _sectionName()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit section(const std::string §ionName) : _sectionName(sectionName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &name()
|
||||||
|
{
|
||||||
|
return _sectionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string getValue(const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_sectionMap.count(Key))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return _sectionMap[Key].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setName(const std::string &name, const int &lineNumber)
|
||||||
|
{
|
||||||
|
_sectionName = name;
|
||||||
|
_lineNumber = lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(const std::string &Key, const std::string &Value, const int line)
|
||||||
|
{
|
||||||
|
_sectionMap[Key].Value = Value;
|
||||||
|
_sectionMap[Key].lineNumber = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(section &sec)
|
||||||
|
{
|
||||||
|
_sectionMap.insert(sec._sectionMap.begin(), sec._sectionMap.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isKeyExist(const std::string &Key)
|
||||||
|
{
|
||||||
|
return !_sectionMap.count(Key) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getEndSection()
|
||||||
|
{
|
||||||
|
int line = -1;
|
||||||
|
|
||||||
|
if (_sectionMap.empty() && _sectionName != "")
|
||||||
|
{
|
||||||
|
return _lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &data : _sectionMap)
|
||||||
|
{
|
||||||
|
if (data.second.lineNumber > line)
|
||||||
|
{
|
||||||
|
line = data.second.lineNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLine(const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_sectionMap.count(Key))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return _sectionMap[Key].lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string operator[](const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_sectionMap.count(Key))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return _sectionMap[Key].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
_lineNumber = -1;
|
||||||
|
_sectionName.clear();
|
||||||
|
_sectionMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
return _sectionMap.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int toInt(const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_sectionMap.count(Key))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = std::stoi(_sectionMap[Key].Value);
|
||||||
|
}
|
||||||
|
catch (const std::invalid_argument &e)
|
||||||
|
{
|
||||||
|
INI_DEBUG("Invalid argument: " << e.what() << ",input:\'" << _sectionMap[Key].Value << "\'");
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range &e)
|
||||||
|
{
|
||||||
|
INI_DEBUG("Out of range: " << e.what() << ",input:\'" << _sectionMap[Key].Value << "\'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toString(const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_sectionMap.count(Key))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return _sectionMap[Key].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring toWString(const std::string &Key)
|
||||||
|
{
|
||||||
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||||
|
return converter.from_bytes(toString(Key));
|
||||||
|
}
|
||||||
|
|
||||||
|
double toDouble(const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_sectionMap.count(Key))
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double result = 0.0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = std::stod(_sectionMap[Key].Value);
|
||||||
|
}
|
||||||
|
catch (const std::invalid_argument &e)
|
||||||
|
{
|
||||||
|
INI_DEBUG("Invalid argument: " << e.what() << ",input:\'" << _sectionMap[Key].Value << "\'");
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range &e)
|
||||||
|
{
|
||||||
|
INI_DEBUG("Out of range: " << e.what() << ",input:\'" << _sectionMap[Key].Value << "\'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo : add toString() / toInt() / toDouble()
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _sectionName;
|
||||||
|
std::map<std::string, KeyValueNode> _sectionMap;
|
||||||
|
int _lineNumber = -1; // text line start with 1
|
||||||
|
};
|
||||||
|
|
||||||
|
class ini
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void addSection(section &sec)
|
||||||
|
{
|
||||||
|
if (_iniInfoMap.count(sec.name())) // if exist,need to merge
|
||||||
|
{
|
||||||
|
_iniInfoMap[sec.name()].append(sec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_iniInfoMap.emplace(sec.name(), sec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeSection(const std::string §ionName)
|
||||||
|
{
|
||||||
|
if (!_iniInfoMap.count(sectionName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_iniInfoMap.erase(sectionName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSectionExists(const std::string §ionName)
|
||||||
|
{
|
||||||
|
return !_iniInfoMap.count(sectionName) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// may contains default of Unnamed section with ""
|
||||||
|
std::list<std::string> getSectionsList()
|
||||||
|
{
|
||||||
|
std::list<std::string> sectionList;
|
||||||
|
for (const auto &data : _iniInfoMap)
|
||||||
|
{
|
||||||
|
if (data.first == "" && data.second.isEmpty()) // default section: no section name,if empty,not count it.
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sectionList.emplace_back(data.first);
|
||||||
|
}
|
||||||
|
return sectionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
const section &operator[](const std::string §ionName)
|
||||||
|
{
|
||||||
|
if (!_iniInfoMap.count(sectionName))
|
||||||
|
{
|
||||||
|
return _iniInfoMap[""];
|
||||||
|
}
|
||||||
|
return _iniInfoMap[sectionName];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t getSectionSize()
|
||||||
|
{
|
||||||
|
return _iniInfoMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getValue(const std::string §ionName, const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_iniInfoMap.count(sectionName))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return _iniInfoMap[sectionName][Key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// for none section
|
||||||
|
int getLine(const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_iniInfoMap.count(""))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return _iniInfoMap[""].getLine(Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for section-key
|
||||||
|
int getLine(const std::string §ionName, const std::string &Key)
|
||||||
|
{
|
||||||
|
if (!_iniInfoMap.count(sectionName))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return _iniInfoMap[sectionName].getLine(Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void clear() { _iniInfoMap.clear(); }
|
||||||
|
inline bool empty() { return _iniInfoMap.empty(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::map<std::string /*Section Name*/, section> _iniInfoMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo if file is modified,never write back
|
||||||
|
class IniManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit IniManager(const std::string &configFileName) : _configFileName(configFileName)
|
||||||
|
{
|
||||||
|
parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
~IniManager()
|
||||||
|
{
|
||||||
|
_iniFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
section operator[](const std::string §ionName)
|
||||||
|
{
|
||||||
|
return _iniData[sectionName];
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse()
|
||||||
|
{
|
||||||
|
_iniFile.open(_configFileName, std::ifstream::in | std::ifstream::out | std::fstream::app);
|
||||||
|
if (!_iniFile.is_open())
|
||||||
|
{
|
||||||
|
INI_DEBUG("Failed to open the input INI file for parsing!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_iniData.clear();
|
||||||
|
|
||||||
|
_iniFile.seekg(0, _iniFile.beg);
|
||||||
|
std::string data, sectionName;
|
||||||
|
int sectionLine = -1;
|
||||||
|
|
||||||
|
section sectionRecord;
|
||||||
|
|
||||||
|
_SumOfLines = 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::getline(_iniFile, data);
|
||||||
|
|
||||||
|
if (!filterData(data))
|
||||||
|
{
|
||||||
|
++_SumOfLines;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.find('[') == 0) // section
|
||||||
|
{
|
||||||
|
if (!sectionRecord.isEmpty() || sectionRecord.name() != "")
|
||||||
|
{
|
||||||
|
_iniData.addSection(sectionRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t first = data.find('[');
|
||||||
|
size_t last = data.find(']');
|
||||||
|
|
||||||
|
if (last == std::string::npos)
|
||||||
|
{
|
||||||
|
++_SumOfLines;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionName = data.substr(first + 1, last - first - 1);
|
||||||
|
sectionLine = _SumOfLines;
|
||||||
|
|
||||||
|
sectionRecord.clear();
|
||||||
|
sectionRecord.setName(sectionName, sectionLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pos = data.find('=');
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{ // k=v
|
||||||
|
std::string key = data.substr(0, pos);
|
||||||
|
std::string value = data.substr(pos + 1);
|
||||||
|
|
||||||
|
trimEdges(key);
|
||||||
|
trimEdges(value);
|
||||||
|
|
||||||
|
sectionRecord.setValue(key, value, _SumOfLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
++_SumOfLines;
|
||||||
|
|
||||||
|
} while (!_iniFile.eof());
|
||||||
|
|
||||||
|
if (!sectionRecord.isEmpty())
|
||||||
|
{
|
||||||
|
sectionRecord.setName(sectionName, -1);
|
||||||
|
_iniData.addSection(sectionRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_iniFile.is_open())
|
||||||
|
{
|
||||||
|
_iniFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modify(const std::string &Section, const std::string &Key, const std::string &Value, const std::string &comment = "")
|
||||||
|
{ // todo: insert comment before k=v
|
||||||
|
parse();
|
||||||
|
|
||||||
|
if (Key == "" || Value == "")
|
||||||
|
{
|
||||||
|
INI_DEBUG("Invalid parameter input: Key[" << Key << "],Value[" << Value << "]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string keyValueData = Key + "=" + Value + "\n";
|
||||||
|
if (comment.length() > 0)
|
||||||
|
{
|
||||||
|
keyValueData = comment + "\n" + keyValueData;
|
||||||
|
if (comment[0] != ';')
|
||||||
|
{
|
||||||
|
keyValueData = ";" + keyValueData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &tempFile = ".temp.ini";
|
||||||
|
std::fstream input(_configFileName, std::ifstream::in | std::ifstream::out | std::fstream::app);
|
||||||
|
std::ofstream output(tempFile);
|
||||||
|
|
||||||
|
if (!input.is_open())
|
||||||
|
{
|
||||||
|
INI_DEBUG("Failed to open the input INI file for modification!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!output.is_open())
|
||||||
|
{
|
||||||
|
INI_DEBUG("Failed to open the input INI file for modification!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int line_number_mark = -1;
|
||||||
|
bool isInputDataWited = false;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// exist key at one section replace it, or need to create it
|
||||||
|
if (_iniData.isSectionExists(Section))
|
||||||
|
{
|
||||||
|
line_number_mark = (*this)[Section].getLine(Key);
|
||||||
|
|
||||||
|
if (line_number_mark == -1)
|
||||||
|
{ // section exist, key not exist
|
||||||
|
line_number_mark = (*this)[Section].getEndSection();
|
||||||
|
|
||||||
|
std::string lineData;
|
||||||
|
int input_line_number = 0;
|
||||||
|
while (std::getline(input, lineData))
|
||||||
|
{
|
||||||
|
++input_line_number;
|
||||||
|
|
||||||
|
if (input_line_number == (line_number_mark + 1))
|
||||||
|
{ // new line,append to next line
|
||||||
|
isInputDataWited = true;
|
||||||
|
output << keyValueData;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << lineData << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.eof() && !isInputDataWited)
|
||||||
|
{
|
||||||
|
isInputDataWited = true;
|
||||||
|
output << keyValueData;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_number_mark <= 0) // not found key at config file
|
||||||
|
{
|
||||||
|
input.seekg(0, input.beg);
|
||||||
|
|
||||||
|
bool isHoldSection = false;
|
||||||
|
std::string newLine = "\n\n";
|
||||||
|
if (Section != "" && Section.find("[") == std::string::npos && Section.find("]") == std::string::npos && Section.find("=") == std::string::npos)
|
||||||
|
{
|
||||||
|
if (_iniData.empty() || _iniData.getSectionSize() <= 0)
|
||||||
|
{
|
||||||
|
newLine.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
isHoldSection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1.section is exist or empty section
|
||||||
|
if (_iniData.isSectionExists(Section) || Section == "")
|
||||||
|
{
|
||||||
|
// write key/value to head
|
||||||
|
if (isHoldSection)
|
||||||
|
{
|
||||||
|
output << newLine << "[" << Section << "]" << "\n";
|
||||||
|
}
|
||||||
|
output << keyValueData;
|
||||||
|
// write others
|
||||||
|
std::string lineData;
|
||||||
|
while (std::getline(input, lineData))
|
||||||
|
{
|
||||||
|
output << lineData << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2.section is not exist
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// write others
|
||||||
|
std::string lineData;
|
||||||
|
while (std::getline(input, lineData))
|
||||||
|
{
|
||||||
|
output << lineData << "\n";
|
||||||
|
}
|
||||||
|
// write key/value to end
|
||||||
|
if (isHoldSection)
|
||||||
|
{
|
||||||
|
output << newLine << "[" << Section << "]" << "\n";
|
||||||
|
}
|
||||||
|
output << keyValueData;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // found, replace it
|
||||||
|
|
||||||
|
std::string lineData;
|
||||||
|
int input_line_number = 0;
|
||||||
|
|
||||||
|
while (std::getline(input, lineData))
|
||||||
|
{
|
||||||
|
++input_line_number;
|
||||||
|
|
||||||
|
// delete old comment if new comment is set
|
||||||
|
if (input_line_number == (line_number_mark - 1) && lineData.length() > 0 && lineData[0] == ';' && comment != "")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_line_number == line_number_mark)
|
||||||
|
{ // replace to this line
|
||||||
|
output << keyValueData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output << lineData << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
INI_DEBUG("error! inicpp lost process of modify function");
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
// clear work
|
||||||
|
input.close();
|
||||||
|
output.close();
|
||||||
|
|
||||||
|
std::remove(_configFileName.c_str());
|
||||||
|
std::rename(tempFile.c_str(), _configFileName.c_str());
|
||||||
|
|
||||||
|
// reload
|
||||||
|
parse();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modify(const std::string &Section, const std::string &Key, const int &Value, const std::string &comment = "")
|
||||||
|
{
|
||||||
|
std::string stringValue = std::to_string(Value);
|
||||||
|
return modify(Section, Key, stringValue, comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modify(const std::string &Section, const std::string &Key, const double &Value, const std::string &comment = "")
|
||||||
|
{
|
||||||
|
std::string stringValue = std::to_string(Value);
|
||||||
|
return modify(Section, Key, stringValue, comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modify(const std::string &Section, const std::string &Key, const std::wstring &Value, const std::string &comment = "")
|
||||||
|
{
|
||||||
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||||
|
std::string stringValue = converter.to_bytes(Value);
|
||||||
|
|
||||||
|
return modify(Section, Key, stringValue, comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modifyComment(const std::string &Section, const std::string &Key, const std::string &comment)
|
||||||
|
{
|
||||||
|
return modify(Section, Key, (*this)[Section][Key], comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSectionExists(const std::string §ionName)
|
||||||
|
{
|
||||||
|
return _iniData.isSectionExists(sectionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::list<std::string> getSectionsList()
|
||||||
|
{
|
||||||
|
return _iniData.getSectionsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool filterData(std::string &data)
|
||||||
|
{
|
||||||
|
if (data.length() == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[0] == ';')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[0] == '#')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void trimEdges(std::string &data)
|
||||||
|
{
|
||||||
|
// remove left ' ' and '\t'
|
||||||
|
data.erase(data.begin(), std::find_if(data.begin(), data.end(), [](unsigned char c)
|
||||||
|
{ return !std::isspace(c); }));
|
||||||
|
// remove right ' ' and '\t'
|
||||||
|
data.erase(std::find_if(data.rbegin(), data.rend(), [](unsigned char c)
|
||||||
|
{ return !std::isspace(c); })
|
||||||
|
.base(),
|
||||||
|
data.end());
|
||||||
|
|
||||||
|
INI_DEBUG( "trimEdges data:|" << data << "|");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ini _iniData;
|
||||||
|
int _SumOfLines;
|
||||||
|
std::fstream _iniFile;
|
||||||
|
std::string _configFileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
229
src/comframe.cpp
229
src/comframe.cpp
|
@ -12,121 +12,120 @@
|
||||||
#include "telemetry.h"
|
#include "telemetry.h"
|
||||||
|
|
||||||
|
|
||||||
|
int get_com_tty_id(const char* path, unsigned int baudRate) {
|
||||||
|
int tty_id = open((const char*)path, O_RDWR | O_NOCTTY);
|
||||||
|
if (tty_id < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "...error open tty failed: %s @%s:%d\n", strerror(errno), __FILE__, __LINE__);
|
||||||
|
exit(__LINE__);
|
||||||
|
}
|
||||||
|
init_tty(tty_id, baudRate);
|
||||||
|
printf("COM '%s' is ready!\n", path);
|
||||||
|
return tty_id;
|
||||||
|
}
|
||||||
|
|
||||||
//int get_com_tty_id(const char* path, unsigned int baudRate) {
|
void init_tty(int tty_id, unsigned int baudRate) {
|
||||||
// int tty_id = open((const char*)path, O_RDWR | O_NOCTTY);
|
struct termios options, old;
|
||||||
// if (tty_id < 0)
|
// deploy usart par
|
||||||
// {
|
memset(&options, 0, sizeof(options));
|
||||||
// PrintFilePos(); fprintf(stderr, "...error open tty failed: %s @%s:%d\n", strerror(errno), __FILE__, __LINE__);
|
int ret = tcgetattr(tty_id, &old);
|
||||||
// exit(__LINE__);
|
if (ret != 0)
|
||||||
// }
|
{
|
||||||
// init_tty(tty_id, baudRate);
|
fprintf(stderr, "...error tcgetattr() failed: %s\n @%s:%d", strerror(errno), __FILE__, __LINE__);
|
||||||
// PrintFilePos(); printf("COM '%s' is ready!\n", path);
|
exit(__LINE__);
|
||||||
// return tty_id;
|
}
|
||||||
//}
|
|
||||||
//
|
|
||||||
//void init_tty(int tty_id, unsigned int baudRate) {
|
tcflush(tty_id, TCIOFLUSH);
|
||||||
// struct termios options, old;
|
|
||||||
// // deploy usart par
|
switch (baudRate) {
|
||||||
// memset(&options, 0, sizeof(options));
|
case 9600:
|
||||||
// int ret = tcgetattr(tty_id, &old);
|
cfsetispeed(&options, B9600);
|
||||||
// if (ret != 0)
|
cfsetospeed(&options, B9600);
|
||||||
// {
|
break;
|
||||||
// PrintFilePos(); fprintf(stderr, "...error tcgetattr() failed: %s\n @%s:%d", strerror(errno), __FILE__, __LINE__);
|
case 19200:
|
||||||
// exit(__LINE__);
|
cfsetispeed(&options, B19200);
|
||||||
// }
|
cfsetospeed(&options, B19200);
|
||||||
//
|
break;
|
||||||
//
|
case 38400:
|
||||||
// tcflush(tty_id, TCIOFLUSH);
|
cfsetispeed(&options, B38400);
|
||||||
//
|
cfsetospeed(&options, B38400);
|
||||||
// switch (baudRate) {
|
break;
|
||||||
// case 9600:
|
case 57600:
|
||||||
// cfsetispeed(&options, B9600);
|
cfsetispeed(&options, B57600);
|
||||||
// cfsetospeed(&options, B9600);
|
cfsetospeed(&options, B57600);
|
||||||
// break;
|
break;
|
||||||
// case 19200:
|
case 115200:
|
||||||
// cfsetispeed(&options, B19200);
|
cfsetispeed(&options, B115200);
|
||||||
// cfsetospeed(&options, B19200);
|
cfsetospeed(&options, B115200);
|
||||||
// break;
|
break;
|
||||||
// case 38400:
|
case 576000:
|
||||||
// cfsetispeed(&options, B38400);
|
cfsetispeed(&options, B576000);
|
||||||
// cfsetospeed(&options, B38400);
|
cfsetospeed(&options, B576000);
|
||||||
// break;
|
break;
|
||||||
// case 57600:
|
case 921600:
|
||||||
// cfsetispeed(&options, B57600);
|
cfsetispeed(&options, B921600);
|
||||||
// cfsetospeed(&options, B57600);
|
cfsetospeed(&options, B921600);
|
||||||
// break;
|
break;
|
||||||
// case 115200:
|
case 2000000:
|
||||||
// cfsetispeed(&options, B115200);
|
cfsetispeed(&options, B2000000);
|
||||||
// cfsetospeed(&options, B115200);
|
cfsetospeed(&options, B2000000);
|
||||||
// break;
|
break;
|
||||||
// case 576000:
|
case 3000000:
|
||||||
// cfsetispeed(&options, B576000);
|
cfsetispeed(&options, B3000000);
|
||||||
// cfsetospeed(&options, B576000);
|
cfsetospeed(&options, B3000000);
|
||||||
// break;
|
break;
|
||||||
// case 921600:
|
default:
|
||||||
// cfsetispeed(&options, B921600);
|
printf("****Error: baud rate %u too low!\n", baudRate);
|
||||||
// cfsetospeed(&options, B921600);
|
exit(__LINE__);
|
||||||
// break;
|
break;
|
||||||
// case 2000000:
|
}
|
||||||
// cfsetispeed(&options, B2000000);
|
switch (1)
|
||||||
// cfsetospeed(&options, B2000000);
|
{
|
||||||
// break;
|
case 0:
|
||||||
// case 3000000:
|
options.c_cflag &= ~PARENB;
|
||||||
// cfsetispeed(&options, B3000000);
|
options.c_cflag &= ~INPCK;
|
||||||
// cfsetospeed(&options, B3000000);
|
break;
|
||||||
// break;
|
case 1:
|
||||||
// default:
|
options.c_cflag |= (PARODD //使用奇校验代替偶校验
|
||||||
// PrintFilePos(); printf("****Error: baud rate %u too low!\n", baudRate);
|
| PARENB);//校验位有效
|
||||||
// exit(__LINE__);
|
options.c_iflag |= INPCK; //校验有效
|
||||||
// break;
|
break;
|
||||||
// }
|
case 2:
|
||||||
// switch (1)
|
options.c_cflag |= PARENB;
|
||||||
// {
|
options.c_cflag &= ~PARODD;
|
||||||
// case 0:
|
options.c_iflag |= INPCK;
|
||||||
// options.c_cflag &= ~PARENB;
|
break;
|
||||||
// options.c_cflag &= ~INPCK;
|
case 3:
|
||||||
// break;
|
options.c_cflag &= ~PARENB;
|
||||||
// case 1:
|
options.c_cflag &= ~CSTOPB;
|
||||||
// options.c_cflag |= (PARODD //使用奇校验代替偶校验
|
break;
|
||||||
// | PARENB);//校验位有效
|
default:
|
||||||
// options.c_iflag |= INPCK; //校验有效
|
options.c_cflag &= ~PARENB;
|
||||||
// break;
|
break;
|
||||||
// case 2:
|
}
|
||||||
// options.c_cflag |= PARENB;
|
|
||||||
// options.c_cflag &= ~PARODD;
|
options.c_cflag |= (CLOCAL | CREAD);
|
||||||
// options.c_iflag |= INPCK;
|
options.c_cflag &= ~CSIZE;
|
||||||
// break;
|
options.c_cflag &= ~CRTSCTS;
|
||||||
// case 3:
|
options.c_cflag |= CS8;
|
||||||
// options.c_cflag &= ~PARENB;
|
options.c_cflag &= ~CSTOPB;
|
||||||
// options.c_cflag &= ~CSTOPB;
|
options.c_oflag = 0;
|
||||||
// break;
|
options.c_lflag = 0;
|
||||||
// default:
|
options.c_cc[VTIME] = 0;
|
||||||
// options.c_cflag &= ~PARENB;
|
options.c_cc[VMIN] = 0;
|
||||||
// break;
|
// 启用输出的XON/XOFF控制字符
|
||||||
// }
|
// Enable software flow control (XON/XOFF) for both input and output
|
||||||
//
|
options.c_iflag |= (IXON | IXOFF); // Enable input and output XON/XOFF control characters
|
||||||
// options.c_cflag |= (CLOCAL | CREAD);
|
options.c_oflag |= (IXON | IXOFF); // Enable input and output XON/XOFF control characters
|
||||||
// options.c_cflag &= ~CSIZE;
|
tcflush(tty_id, TCIFLUSH);
|
||||||
// options.c_cflag &= ~CRTSCTS;
|
|
||||||
// options.c_cflag |= CS8;
|
if ((tcsetattr(tty_id, TCSANOW, &options)) != 0)
|
||||||
// options.c_cflag &= ~CSTOPB;
|
{
|
||||||
// options.c_oflag = 0;
|
fprintf(stderr, "...error tcsetattr failed:%s\n", strerror(errno));
|
||||||
// options.c_lflag = 0;
|
exit(__LINE__);
|
||||||
// options.c_cc[VTIME] = 0;
|
}
|
||||||
// options.c_cc[VMIN] = 0;
|
}
|
||||||
// // 启用输出的XON/XOFF控制字符
|
|
||||||
// // Enable software flow control (XON/XOFF) for both input and output
|
|
||||||
// options.c_iflag |= (IXON | IXOFF); // Enable input and output XON/XOFF control characters
|
|
||||||
// options.c_oflag |= (IXON | IXOFF); // Enable input and output XON/XOFF control characters
|
|
||||||
// tcflush(tty_id, TCIFLUSH);
|
|
||||||
//
|
|
||||||
// if ((tcsetattr(tty_id, TCSANOW, &options)) != 0)
|
|
||||||
// {
|
|
||||||
// PrintFilePos(); fprintf(stderr, "...error tcsetattr failed:%s\n", strerror(errno));
|
|
||||||
// exit(__LINE__);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
uint16_t ComFramePayload_EvalChecksum(const struct ComFrameHeader* header, const void* payload) {
|
uint16_t ComFramePayload_EvalChecksum(const struct ComFrameHeader* header, const void* payload) {
|
||||||
size_t length = ComFrame_PAYLOAD_LENGTH(header);
|
size_t length = ComFrame_PAYLOAD_LENGTH(header);
|
||||||
|
@ -280,7 +279,7 @@ ComFrame* ComFrame_ReceiveEx(int tty_id, void* buffer, const size_t buffer_size,
|
||||||
#endif
|
#endif
|
||||||
pred_size = ComFrame_LENGTH(((uint8_t*)buffer) + offset);
|
pred_size = ComFrame_LENGTH(((uint8_t*)buffer) + offset);
|
||||||
if (pred_size > buffer_size) {
|
if (pred_size > buffer_size) {
|
||||||
PrintFilePos(); fprintf(stderr, "data size is too large (%zu)\n", pred_size);
|
fprintf(stderr, "data size is too large (%zu)\n", pred_size);
|
||||||
find_head = false;
|
find_head = false;
|
||||||
pred_size = COM_FRAME_RECEIVE_PRED_SIZE;
|
pred_size = COM_FRAME_RECEIVE_PRED_SIZE;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "dataqueue.hpp"
|
#include "dataqueue.hpp"
|
||||||
|
|
||||||
std::unordered_map<std::string, std::vector<std::pair<event_callback, void*>>> _events;
|
std::unordered_map<std::string, std::vector<std::pair<event_callback, void*>>> _events;
|
||||||
bool _event_thread_running = false;
|
|
||||||
DataQueue<std::tuple<const char*, event_callback, void*, void*>> _event_queue;
|
DataQueue<std::tuple<const char*, event_callback, void*, void*>> _event_queue;
|
||||||
|
|
||||||
void sys_event(const char *event_name, void *args) {
|
void sys_event(const char *event_name, void *args) {
|
||||||
|
@ -35,9 +34,12 @@ int sys_event_unregister(const char *event_name, event_callback callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* sys_event_thread(void*) {
|
void* sys_event_thread(void*) {
|
||||||
_event_thread_running = true;
|
while (true) {
|
||||||
while (_event_thread_running) {
|
const char* event_name;
|
||||||
auto [event_name, callback, args, user_data] = _event_queue.Pop();
|
event_callback callback;
|
||||||
|
void* args;
|
||||||
|
void* user_data;
|
||||||
|
std::tie(event_name, callback, args, user_data) = _event_queue.Pop();
|
||||||
callback(event_name, args, user_data);
|
callback(event_name, args, user_data);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -1,3 +1,37 @@
|
||||||
|
#include <pthread.h>
|
||||||
#include "extern_interface.h"
|
#include "extern_interface.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "inicpp.hpp"
|
||||||
|
|
||||||
|
static et_callback_t et_callback;
|
||||||
|
static pthread_t event_thread;
|
||||||
|
static pthread_t upperhost_thread;
|
||||||
|
static pthread_t telemetry_thread;
|
||||||
|
|
||||||
|
int extern_interface_init(const char* config_path, et_callback_t cb) {
|
||||||
|
inicpp::IniManager manager(config_path);
|
||||||
|
et_callback = cb;
|
||||||
|
|
||||||
|
pthread_create(&event_thread, NULL, sys_event_thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void extern_interface_send(uint32_t type, size_t len, union PacketData data) {
|
||||||
|
switch (type) {
|
||||||
|
case ET_TYPE_COMMAND:
|
||||||
|
sys_event("send_command", data.pd_pointer);
|
||||||
|
break;
|
||||||
|
case ET_TYPE_AUDIO:
|
||||||
|
sys_event("send_audio", data.pd_pointer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void extern_interface_handle(uint32_t type, size_t len, union PacketData data) {
|
||||||
|
et_callback(type, len, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_telemetry_request_data(TelemetryRequestData* data) {
|
||||||
|
extern_interface_handle(ET_TYPE_TELEMETRY_REQUEST, sizeof(TelemetryRequestData), { .pd_pointer = data });
|
||||||
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include "telemetry.h"
|
#include "telemetry.h"
|
||||||
#include "dataqueue.h"
|
#include "dataqueue.hpp"
|
||||||
#include "defines.h"
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
extern bool g_bKeepSysRuning;
|
#define PrintFilePos()
|
||||||
|
|
||||||
void play_text(char* pTextStr, int iRepeat_times);
|
void play_text(char* pTextStr, int iRepeat_times);
|
||||||
|
|
||||||
// int32_t g_iExternTimeDifference = 0;
|
// int32_t g_iExternTimeDifference = 0;
|
||||||
|
|
|
@ -32,7 +32,7 @@ static interactive_func interactive = NULL;
|
||||||
static context_func setup = NULL;
|
static context_func setup = NULL;
|
||||||
static context_func teardown = NULL;
|
static context_func teardown = NULL;
|
||||||
|
|
||||||
static atomic_bool testcase_running = false;
|
static atomic_bool testcase_running;
|
||||||
static jmp_buf testcase_env;
|
static jmp_buf testcase_env;
|
||||||
static int testcase_exit_code = 0;
|
static int testcase_exit_code = 0;
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,5 @@ TEST_CASE(init) {
|
||||||
assert_eq(q.Size(), 0);
|
assert_eq(q.Size(), 0);
|
||||||
END_TEST;
|
END_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER arm-none-linux-gnueabihf-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER arm-none-linux-gnueabihf-g++)
|
|
@ -0,0 +1,5 @@
|
||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER arm-ztkp_openeuler-linux-gnueabi-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER arm-ztkp_openeuler-linux-gnueabi-g++)
|
|
@ -0,0 +1,203 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
###################################################################################
|
||||||
|
project(libgo)
|
||||||
|
|
||||||
|
enable_language(C ASM)
|
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE)
|
||||||
|
else()
|
||||||
|
set(CMAKE_BUILD_TYPE RELEASE)
|
||||||
|
#set(CMAKE_BUILD_TYPE DEBUG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message("------------ Options -------------")
|
||||||
|
message(" CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
||||||
|
message(" CMAKE_COMMAND: ${CMAKE_COMMAND}")
|
||||||
|
|
||||||
|
option(ENABLE_DEBUGGER "enable debugger" OFF)
|
||||||
|
if (ENABLE_DEBUGGER)
|
||||||
|
set(ENABLE_DEBUGGER 1)
|
||||||
|
message (" enable_debugger: yes")
|
||||||
|
else()
|
||||||
|
set(ENABLE_DEBUGGER 0)
|
||||||
|
message (" enable_debugger: no")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(DISABLE_HOOK "disable hook" OFF)
|
||||||
|
if (DISABLE_HOOK)
|
||||||
|
set(ENABLE_HOOK 0)
|
||||||
|
message (" enable_hook: no")
|
||||||
|
else()
|
||||||
|
set(ENABLE_HOOK 1)
|
||||||
|
message (" enable_hook: yes")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (BUILD_DYNAMIC)
|
||||||
|
message (" build dynamic lib: yes")
|
||||||
|
else()
|
||||||
|
message (" build dynamic lib: no")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message("-------------- Env ---------------")
|
||||||
|
message(" CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
|
||||||
|
message(" CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
|
||||||
|
message("----------------------------------")
|
||||||
|
|
||||||
|
configure_file(${PROJECT_SOURCE_DIR}/libgo/common/cmake_config.h.in ${PROJECT_SOURCE_DIR}/libgo/common/cmake_config.h)
|
||||||
|
message("----------------------------------")
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
set(CMAKE_CXX_FLAGS "-std=c++17 -fPIC -Wall ${CMAKE_CXX_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-g")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -DNDEBUG")
|
||||||
|
|
||||||
|
set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS S)
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
message(STATUS "> CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
|
||||||
|
set(ASM_DIR "${PROJECT_SOURCE_DIR}/third_party/boost.context/libs/context/src/asm/")
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm")
|
||||||
|
set(jump_asm_file "${ASM_DIR}jump_arm_aapcs_elf_gas.S")
|
||||||
|
set(make_asm_file "${ASM_DIR}make_arm_aapcs_elf_gas.S")
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
||||||
|
set(jump_asm_file "${ASM_DIR}jump_arm64_aapcs_elf_gas.S")
|
||||||
|
set(make_asm_file "${ASM_DIR}make_arm64_aapcs_elf_gas.S")
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||||
|
set(jump_asm_file "${ASM_DIR}jump_x86_64_sysv_elf_gas.S")
|
||||||
|
set(make_asm_file "${ASM_DIR}make_x86_64_sysv_elf_gas.S")
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") # macOS
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||||
|
set(jump_asm_file "${ASM_DIR}jump_arm64_aapcs_macho_gas.S")
|
||||||
|
set(make_asm_file "${ASM_DIR}make_arm64_aapcs_macho_gas.S")
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
|
||||||
|
set(jump_asm_file "${ASM_DIR}jump_i386_ms_pe_gas.asm")
|
||||||
|
set(make_asm_file "${ASM_DIR}make_i386_ms_pe_gas.asm")
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||||
|
set(jump_asm_file "${ASM_DIR}jump_x86_64_ms_pe_gas.asm")
|
||||||
|
set(make_asm_file "${ASM_DIR}make_x86_64_ms_pe_gas.asm")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if (NOT jump_asm_file OR NOT make_asm_file)
|
||||||
|
message(FATAL_ERROR "--> select asm source file failed")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
file(COPY ${jump_asm_file} DESTINATION ${PROJECT_SOURCE_DIR}/libgo/context)
|
||||||
|
file(COPY ${make_asm_file} DESTINATION ${PROJECT_SOURCE_DIR}/libgo/context)
|
||||||
|
else()
|
||||||
|
message("--> select asm source file, please wait about 5 seconds ...")
|
||||||
|
execute_process(COMMAND "${PROJECT_SOURCE_DIR}/third_party/select_asm.sh" "${PROJECT_SOURCE_DIR}" "jump" OUTPUT_VARIABLE jump_asm_file)
|
||||||
|
execute_process(COMMAND "${PROJECT_SOURCE_DIR}/third_party/select_asm.sh" "${PROJECT_SOURCE_DIR}" "make" OUTPUT_VARIABLE make_asm_file)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 输出选择的汇编文件路径
|
||||||
|
message(STATUS "Jump ASM File: ${jump_asm_file}")
|
||||||
|
message(STATUS "Make ASM File: ${make_asm_file}")
|
||||||
|
elseif (WIN32)
|
||||||
|
# windows platform
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd /EHsc")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /EHsc")
|
||||||
|
|
||||||
|
#set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS asm)
|
||||||
|
#file(COPY ${PROJECT_SOURCE_DIR}/third_party/boost.context/libs/context/src/asm/make_x86_64_ms_pe_masm.asm DESTINATION ${PROJECT_SOURCE_DIR}/libgo/context)
|
||||||
|
#file(COPY ${PROJECT_SOURCE_DIR}/third_party/boost.context/libs/context/src/asm/jump_x86_64_ms_pe_masm.asm DESTINATION ${PROJECT_SOURCE_DIR}/libgo/context)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message("------------ Cxx flags -------------")
|
||||||
|
message(" CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}: ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||||
|
message("------------------------------------")
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR})
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/common CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/context CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/task CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/scheduler CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/sync CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/timer CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/cls CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/defer CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/pool CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/debug CO_SRC_LIST)
|
||||||
|
|
||||||
|
if (NOT DISABLE_HOOK)
|
||||||
|
if (UNIX)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/netio/unix CO_SRC_LIST)
|
||||||
|
elseif (WIN32)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/libgo/netio/windows)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/netio/windows CO_SRC_LIST)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/context/fiber CO_SRC_LIST)
|
||||||
|
list(APPEND CO_SRC_LIST ${PROJECT_SOURCE_DIR}/libgo/netio/windows/xhook/xhook.cpp)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/libgo/netio/disable_hook CO_SRC_LIST)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(TARGET "libgo")
|
||||||
|
set(STATIC_T "libgo_static")
|
||||||
|
set(STATIC_HOOK "static_hook")
|
||||||
|
|
||||||
|
list(APPEND CO_SRC_LIST ${jump_asm_file})
|
||||||
|
list(APPEND CO_SRC_LIST ${make_asm_file})
|
||||||
|
add_library("${STATIC_T}" STATIC ${CO_SRC_LIST})
|
||||||
|
set_target_properties("${STATIC_T}" PROPERTIES OUTPUT_NAME "${TARGET}")
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
install(TARGETS ${STATIC_T} LIBRARY DESTINATION "lib" ARCHIVE DESTINATION "lib")
|
||||||
|
install(DIRECTORY ${PROJECT_SOURCE_DIR}/libgo/ DESTINATION "include/libgo" FILES_MATCHING PATTERN "*.h")
|
||||||
|
#PATTERN "windows" EXCLUDE
|
||||||
|
|
||||||
|
add_library("${STATIC_HOOK}" STATIC "${PROJECT_SOURCE_DIR}/libgo/netio/unix/static_hook/static_hook.cpp")
|
||||||
|
|
||||||
|
if (BUILD_DYNAMIC)
|
||||||
|
set(SHARED_T "libgo_dynamic")
|
||||||
|
add_library("${SHARED_T}" SHARED ${CO_SRC_LIST})
|
||||||
|
set_target_properties("${SHARED_T}" PROPERTIES OUTPUT_NAME "${TARGET}")
|
||||||
|
target_link_libraries("${SHARED_T}" ${LINK_LIBS} -ldl)
|
||||||
|
install(TARGETS ${SHARED_T} LIBRARY DESTINATION "lib" ARCHIVE DESTINATION "lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(debug
|
||||||
|
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=DEBUG ${CMAKE_SOURCE_DIR}
|
||||||
|
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
COMMENT "Switch CMAKE_BUILD_TYPE to Debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(release
|
||||||
|
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=RELEASE ${CMAKE_SOURCE_DIR}
|
||||||
|
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
COMMENT "Switch CMAKE_BUILD_TYPE to Release"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PROFILE_FLAGS "-pg ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||||
|
|
||||||
|
#message("PROFILE_FLAGS: ${PROFILE_FLAGS}")
|
||||||
|
add_custom_target(profile
|
||||||
|
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=PROFILE -DCMAKE_CXX_FLAGS_PROFILE=\\'${PROFILE_FLAGS}\\' ${CMAKE_SOURCE_DIR}
|
||||||
|
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target all
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
COMMENT "Switch CMAKE_BUILD_TYPE to PROFILE"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(uninstall
|
||||||
|
COMMAND rm ${CMAKE_INSTALL_PREFIX}/lib/liblibgo.a ${CMAKE_INSTALL_PREFIX}/lib/liblibgo.so ${CMAKE_INSTALL_PREFIX}/lib/liblibgo_main.a -f
|
||||||
|
COMMAND rm ${CMAKE_INSTALL_PREFIX}/include/libgo -rf
|
||||||
|
)
|
||||||
|
|
||||||
|
elseif (WIN32)
|
||||||
|
set_target_properties("${STATIC_T}" PROPERTIES COMPILE_FLAGS "/wd4819 /wd4267")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
if (BOOST_ROOT)
|
||||||
|
add_subdirectory(${PROJECT_SOURCE_DIR}/test/gtest_unit)
|
||||||
|
add_subdirectory(${PROJECT_SOURCE_DIR}/tutorial)
|
||||||
|
endif()
|
||||||
|
endif()
|
Loading…
Reference in New Issue