1451 lines
44 KiB
C++
1451 lines
44 KiB
C++
/*
|
||
* utility.cpp
|
||
*
|
||
* Created on: 10 дек. 2014 г.
|
||
* Author: ivanov.i
|
||
*/
|
||
|
||
#include <algorithm> // std::sort
|
||
#include <sstream>
|
||
#include <stdexcept>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <dirent.h>
|
||
#include <iomanip>
|
||
#include <iostream>
|
||
#include <fstream>
|
||
#include <fcntl.h>
|
||
#include <stdio.h>
|
||
#include <vector>
|
||
#include <math.h>
|
||
#include <ctime>
|
||
#include <stdio.h>
|
||
#include <cstdio>
|
||
|
||
#include <stdlib.h>
|
||
#include <iostream>
|
||
#include <cstdio>
|
||
|
||
#include <string.h>
|
||
#include <sys/types.h>
|
||
|
||
|
||
|
||
#include <errno.h> // Error number definitions
|
||
|
||
//#include <sys/types.h>lo
|
||
#include <sys/stat.h>
|
||
|
||
|
||
//#include <openssl/des.h>
|
||
|
||
#ifdef __linux__
|
||
#include <unistd.h> //В C++Builder ругался что нет
|
||
#include <sys/vfs.h> //В C++Builder ругался что нет
|
||
#include <sys/time.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <netdb.h>
|
||
#elif _WIN32
|
||
#include <windows.h>
|
||
#else
|
||
|
||
#endif
|
||
|
||
#include "utility.h"
|
||
|
||
namespace UtilityW
|
||
{
|
||
time_t g_file_name_cnt_time;
|
||
int g_file_name_cnt=0;
|
||
//Генерировать уникальное имя файла на основе времени и порядкового номера из глобавльной переменной
|
||
std::string getNextFileName()
|
||
{
|
||
if(g_file_name_cnt_time != std::time(0)){
|
||
g_file_name_cnt_time = std::time(0);
|
||
g_file_name_cnt=0;
|
||
}
|
||
g_file_name_cnt++;
|
||
std::stringstream ss;
|
||
ss << g_file_name_cnt_time << "_" << g_file_name_cnt ;
|
||
return ss.str();
|
||
}
|
||
|
||
#ifdef _WIN32
|
||
//------------------------------------------------------------------------------
|
||
void UnixTimeToFileTime(time_t t, LPFILETIME pft)
|
||
{
|
||
// Note that LONGLONG is a 64-bit value
|
||
LONGLONG ll;
|
||
ll = Int32x32To64(t, 10000000) + 116444736000000000;
|
||
pft->dwLowDateTime = (DWORD)ll;
|
||
pft->dwHighDateTime = ll >> 32;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
//После преобразования времени UNIX на структуру FILETIME, другие форматы времени Win32 можно легко получить с помощью функций Win32, как FileTimeToSystemTime() и FileTimeToDosDateTime().
|
||
void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst)
|
||
{
|
||
FILETIME ft;
|
||
UnixTimeToFileTime(t, &ft);
|
||
FileTimeToSystemTime(&ft, pst);
|
||
}
|
||
#endif
|
||
//------------------------------------------------------------------------------
|
||
//Разделитель для директорий
|
||
char separator()
|
||
{
|
||
#ifdef _WIN32
|
||
return '\\';
|
||
#else
|
||
return '/';
|
||
#endif
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
bool deleteFile(std::string fileName)
|
||
{
|
||
bool result=false;
|
||
#ifdef __linux__
|
||
if(unlink(fileName.c_str())==0)
|
||
{
|
||
result=true;
|
||
}
|
||
#elif _WIN32
|
||
if(remove(fileName.c_str())==0)
|
||
{
|
||
result=true;
|
||
}
|
||
#endif
|
||
return result;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
//Получить размер самого большого файла вкатологе
|
||
long getMaxFileSize(std::string path)
|
||
{
|
||
long maxSize=0;
|
||
std::list<std::string> fileList;
|
||
UtilityW::GetFiles(fileList,path);
|
||
std::list<std::string>::const_iterator iterator;
|
||
for (iterator = fileList.begin(); iterator != fileList.end(); ++iterator) {
|
||
std::string fName = *iterator;
|
||
long fSize = UtilityW::getFileSize(fName);
|
||
if(fSize>maxSize)
|
||
maxSize = fSize;
|
||
}
|
||
return maxSize;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
//Проверяем открыт ли сокет
|
||
//timeout - Тайм аут для коннекта в секундах
|
||
/*bool checkPort(const char *hostname,int portno,int timeout)
|
||
{
|
||
#ifdef __linux__
|
||
bool result=false;
|
||
|
||
int sockfd;
|
||
struct sockaddr_in serv_addr;
|
||
struct hostent *server;
|
||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||
if (sockfd >= 0) {
|
||
server = gethostbyname(hostname);
|
||
|
||
if (server == NULL) {
|
||
fprintf(stderr,"ERROR, no such host\n");
|
||
//exit(0);
|
||
}
|
||
|
||
bzero((char *) &serv_addr, sizeof(serv_addr)); //TODO Устаревшая конструкция
|
||
serv_addr.sin_family = AF_INET;
|
||
bcopy((char *)server->h_addr, //TODO Разыменование нулевого указателя, проверка на ИБ
|
||
(char *)&serv_addr.sin_addr.s_addr,
|
||
server->h_length);
|
||
|
||
serv_addr.sin_port = htons(portno);
|
||
|
||
//Чтобы была возможность задать таймаут для подключения делаю неблокирующий сокет
|
||
int flags = fcntl(sockfd, F_GETFL, 0);
|
||
if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||
{
|
||
fprintf(stderr,"ERROR, set O_NONBLOCK!\n");
|
||
}
|
||
|
||
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
|
||
{
|
||
if(errno == EINPROGRESS) //Это не ошибка, это признак того, что соединение все еще не установлено.
|
||
{
|
||
struct timeval ts;
|
||
ts.tv_sec = timeout;
|
||
ts.tv_usec = 0;
|
||
|
||
//int ret = 0;
|
||
fd_set rset, wset;
|
||
FD_ZERO(&rset);
|
||
FD_SET(sockfd, &rset);
|
||
wset = rset; //structure assignment ok
|
||
|
||
if(select(sockfd + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL) > 0)
|
||
result=true;
|
||
|
||
}else{
|
||
// Произошла ошибка сразу же при соединении.
|
||
}
|
||
|
||
} else {
|
||
result=true; //Соединение было установлено за время системного вызова.
|
||
}
|
||
|
||
close(sockfd);
|
||
}
|
||
|
||
|
||
return result;
|
||
#elif _WIN32
|
||
return false;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}*/
|
||
//------------------------------------------------------------------------------
|
||
//Простое вычисление CRC (как для GPS)
|
||
uint8_t CRC8(const signed char *pcBlock, unsigned char len, unsigned char crc)
|
||
{
|
||
for(unsigned char i=0; i < len; i++)
|
||
crc^=pcBlock[i];
|
||
return crc;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Найти файлы в директории и под директории и добавить их в список
|
||
void GetFiles(std::list<std::string>& fileList, std::string directory)
|
||
{
|
||
if(directory.length()>0 && directory[directory.length()-1]!=separator()) directory+=separator();
|
||
#ifdef __linux__
|
||
DIR *dir = opendir(directory.c_str());
|
||
if(dir)
|
||
{
|
||
struct dirent *ent;
|
||
while((ent = readdir(dir)) != NULL)
|
||
{
|
||
if(ent->d_type==0x04)
|
||
{
|
||
if ((strncmp(".", ent->d_name, 1) != 0) && (strncmp("..", ent->d_name, 2) != 0))
|
||
{
|
||
std::string newDir = directory + ent->d_name+"/";
|
||
GetFiles(fileList, newDir);
|
||
}
|
||
}
|
||
else
|
||
if(ent->d_type==0x08)
|
||
{
|
||
std::string fWName = ent->d_name;
|
||
fWName = directory + fWName;
|
||
fileList.push_back(fWName);
|
||
}
|
||
}
|
||
closedir(dir);
|
||
}
|
||
#elif _WIN32
|
||
HANDLE hFind;
|
||
WIN32_FIND_DATAA FindFileData;
|
||
|
||
if ((hFind = FindFirstFileA((std::string(directory+"*.*")).c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) {
|
||
do {
|
||
if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes)
|
||
{
|
||
if ((strncmp(".", FindFileData.cFileName, 1) != 0) && (strncmp("..", FindFileData.cFileName, 2) != 0))
|
||
{
|
||
std::string newDir = directory + FindFileData.cFileName+"\\";
|
||
GetFiles(fileList, newDir);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
std::string fWName = FindFileData.cFileName;
|
||
fWName = directory + fWName;
|
||
fileList.push_back(fWName);
|
||
}
|
||
|
||
} while (FindNextFileA(hFind, &FindFileData));
|
||
FindClose(hFind);
|
||
}
|
||
#else
|
||
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Получить список папок в директории (без подпапок)
|
||
void GetFolders(std::list<std::string>& folderList, std::string directory)
|
||
{
|
||
#ifdef __linux__
|
||
|
||
if(directory.length()>0 && directory[directory.length()-1]!='/') directory+='/';
|
||
DIR *dir = opendir(directory.c_str());
|
||
if(dir)
|
||
{
|
||
struct dirent *ent;
|
||
while((ent = readdir(dir)) != NULL)
|
||
{
|
||
if(ent->d_type==0x04)
|
||
{
|
||
if ((strncmp(".", ent->d_name, 1) != 0) && (strncmp("..", ent->d_name, 2) != 0))
|
||
{
|
||
std::string newDir = directory + ent->d_name+"/";
|
||
folderList.push_back(newDir);
|
||
}
|
||
}
|
||
}
|
||
closedir(dir);
|
||
}
|
||
|
||
#elif _WIN32
|
||
HANDLE hFind;
|
||
WIN32_FIND_DATAA FindFileData;
|
||
|
||
if ((hFind = FindFirstFileA((std::string(directory+"*.*")).c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) {
|
||
do {
|
||
if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes)
|
||
{
|
||
if ((strncmp(".", FindFileData.cFileName, 1) != 0) && (strncmp("..", FindFileData.cFileName, 2) != 0))
|
||
{
|
||
std::string newDir = directory + FindFileData.cFileName+"\\";
|
||
folderList.push_back(newDir);
|
||
}
|
||
}
|
||
} while (FindNextFileA(hFind, &FindFileData));
|
||
FindClose(hFind);
|
||
}
|
||
#else
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Создать папку
|
||
bool createFolder(std::string directory,int mode=0776)
|
||
{
|
||
#ifdef __linux__
|
||
mkdir(directory.c_str(), mode); //Если папки нет то создать её
|
||
chmod(directory.c_str(), mode); //Бывало что при создании права не назначались
|
||
return true;
|
||
#elif _WIN32
|
||
CreateDirectoryA(directory.c_str(), NULL);
|
||
return true;
|
||
#else
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Расшифровать файлик
|
||
bool DeCrypt(std::string strKey, std::string fNameIn, std::string fNameOut)
|
||
{
|
||
/*
|
||
DES_cblock key;
|
||
DES_string_to_key(strKey.c_str(), &key);
|
||
|
||
DES_key_schedule schedule;
|
||
DES_set_key_checked(&key, &schedule);
|
||
|
||
const_DES_cblock input; //Блок данных DES 8 байт (или 64 бита)
|
||
DES_cblock output; //Результирующий блок данных
|
||
|
||
FILE *ptr;
|
||
if((ptr = fopen(fNameIn.c_str(),"rb")) != NULL)
|
||
{
|
||
char prf[4];
|
||
fgets(prf, 4, ptr); //Префикс файла
|
||
if(strcmp("DES", prf)==0)
|
||
{
|
||
FILE* out = fopen(fNameOut.c_str(),"wb");
|
||
if(out!=NULL)
|
||
{
|
||
unsigned int fSize;
|
||
fread((void *)&fSize, 1, sizeof(fSize), ptr);
|
||
//int bSize=ceil(fSize/(float)sizeof(input));
|
||
while(!feof(ptr) && !ferror(ptr))
|
||
{
|
||
memset(&input, 0, sizeof(input)); //Для дебага
|
||
ssize_t bytes_read = fread(input, 1, sizeof(input), ptr);
|
||
if(bytes_read==sizeof(input))
|
||
{
|
||
DES_ecb_encrypt(&input, &output, &schedule, DES_DECRYPT); //Расшифровываем
|
||
//Записываем в файл
|
||
if(fSize>sizeof(output))
|
||
{
|
||
fwrite(&output[0],sizeof(output),1,out);
|
||
fSize = fSize - sizeof(output);
|
||
}else
|
||
{
|
||
fwrite(&output[0],fSize,1,out);
|
||
}
|
||
}
|
||
}
|
||
|
||
if(fflush(out)!=0) std::cout << "!!! fflush = "<< strerror(errno) << " !!!" << std::endl; // Flush to OS
|
||
if(fsync(fileno(out))!=0) std::cout << "!!! fsync = "<< strerror(errno) << " !!!" << std::endl; // Flush to disk
|
||
if(fclose(out)!=0) std::cout << "!!! fclose = "<< strerror(errno) << " !!!" << std::endl; // Close file
|
||
}
|
||
}
|
||
fclose(ptr);
|
||
}
|
||
*/
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Установит знначение бита в заданную позицию
|
||
///pos - Позиция 7..0
|
||
unsigned char setBitVal(unsigned char bit,unsigned char pos,bool val)
|
||
{
|
||
unsigned char v=1;
|
||
v=0x1<<pos;
|
||
if(val)
|
||
{
|
||
bit=bit | v;
|
||
}else
|
||
{
|
||
v=v ^ 0xFF;
|
||
bit=bit & v;
|
||
}
|
||
return bit;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Вернёт значение бита на заданной позиции
|
||
///pos - Позиция 7..0
|
||
bool getBitVal(unsigned char bit,unsigned char pos)
|
||
{
|
||
unsigned char v=1;
|
||
v=v<<pos;
|
||
return (bit & v) == v;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
// get_fs_size - Определяет размер ФС.
|
||
// @param anyfile Путь к любому файлу на этой ФС.
|
||
// @return Размер ФС в блоках*байты.
|
||
long getAllFSSize(std::string anyfile)
|
||
{
|
||
#ifdef __linux__
|
||
struct statfs buf;
|
||
statfs(anyfile.c_str(), &buf);
|
||
return buf.f_blocks*buf.f_bsize;
|
||
#elif _WIN32
|
||
return 0; //В винде нет sys/statvfs.h
|
||
#else
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
// get_fs_free - Определяет свободное место на ФС.
|
||
// @param anyfile Путь к любому файлу на этой ФС.
|
||
// @return Размер ФС в блоках*байты.
|
||
long getFreeFSSize(std::string anyfile)
|
||
{
|
||
#ifdef __linux__
|
||
struct statfs buf;
|
||
statfs(anyfile.c_str(), &buf);
|
||
return buf.f_bfree*buf.f_bsize;
|
||
#elif _WIN32
|
||
return 0; //В винде нет sys/statvfs.h
|
||
#else
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Размер файла в байтах
|
||
long getFileSize(std::string filename)
|
||
{
|
||
/*struct stat stat_buf;
|
||
int rc = stat(filename.c_str(), &stat_buf);
|
||
return rc == 0 ? stat_buf.st_size : -1;*/
|
||
|
||
long size=0;
|
||
FILE *f = fopen(filename.c_str(), "rb");
|
||
if (f)
|
||
{
|
||
fseek(f, 0, SEEK_END);
|
||
size = ftell(f);
|
||
fclose(f);
|
||
}
|
||
return size;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Текущее время в миллисекундах (с учётом того что время не сохрангяется то это время со старта линукса в милисекундах)
|
||
unsigned int getMSecTime()
|
||
{
|
||
#ifdef __linux__
|
||
struct timeval time_now;
|
||
gettimeofday(&time_now, NULL);
|
||
unsigned int curr = time_now.tv_sec * 1000;
|
||
curr += time_now.tv_usec / 1000.0f;
|
||
return curr;
|
||
#elif _WIN32
|
||
std::time_t t = std::time(0);
|
||
return t;
|
||
#else
|
||
#endif
|
||
}
|
||
|
||
//Ротация логов при записи создаёт новый файл но не больше заданого числа лог файлов
|
||
//Ищем файлы с максимальным индексом и проверяем его размер если он больше заданого то создаём новый иначе дописываем
|
||
/* bool logrotate(unsigned int cnt,signed int size, std::string name, std::string data)
|
||
{
|
||
//Формируем список файлов
|
||
std::vector<std::string> vFNames;
|
||
DIR *dir = opendir("/mnt/sd/");
|
||
if(dir)
|
||
{
|
||
struct dirent *ent;
|
||
while((ent = readdir(dir)) != NULL)
|
||
{
|
||
if(std::string(ent->d_name).find(name)!=std::string::npos && std::string(ent->d_name).find(".txt")!=std::string::npos)
|
||
{
|
||
vFNames.push_back(ent->d_name);
|
||
}
|
||
}
|
||
closedir(dir);
|
||
}
|
||
std::sort(vFNames.begin(), vFNames.end());
|
||
|
||
std::string fName;
|
||
if(vFNames.size()>0)
|
||
{
|
||
if(getFileSize(vFNames.at(0))>size)
|
||
{
|
||
std::string sNum = BeforeFirst(AfterLast(vFNames.at(0),'_'),'.');
|
||
sNum = intToString(StdStrToInt(sNum)+1);
|
||
for(unsigned int i=0;i<6-sNum.length();i++) sNum="0"+sNum;
|
||
fName = name+"_"+sNum+".txt";
|
||
}else
|
||
{
|
||
fName = vFNames.at(0);
|
||
}
|
||
if(vFNames.size()>cnt)
|
||
deleteFile(vFNames.at(vFNames.size()-1).c_str()); //Если привысили количество файлов удаляем самый старый
|
||
}else
|
||
{
|
||
fName = "/mnt/sd/" + name + "_000000.txt";
|
||
}
|
||
|
||
std::ofstream myfile (fName.c_str(),std::fstream::app | std::fstream::out);
|
||
if (myfile.is_open())
|
||
{
|
||
myfile << data << "\n";
|
||
myfile.close();
|
||
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
*/
|
||
//---------------------------------------------------------------------------
|
||
//Сохранение лог файла по 10 мегабайт (в 2 файлика)
|
||
//size - мегабайт на 1 файл
|
||
/*bool logrotate(std::string fileName, std::string data,bool cout,int size)
|
||
{
|
||
bool result=false;
|
||
|
||
long fileSize = getFileSize(fileName);
|
||
//Переименовываем файл если он привысил размер
|
||
if(fileSize>1024*1024*size)
|
||
{
|
||
remove(std::string(fileName + ".1").c_str()); //Пытаюсь удалить старый файл
|
||
rename(fileName.c_str(),std::string(fileName+".1").c_str());
|
||
}
|
||
|
||
//Записываем лог
|
||
std::ofstream myfile(fileName.c_str(),std::fstream::app | std::fstream::out);
|
||
if (myfile.is_open())
|
||
{
|
||
timeval curTime;
|
||
gettimeofday(&curTime, NULL);
|
||
int milli = curTime.tv_usec / 1000;
|
||
//std::time_t utime = std::time(0); так как не мог выбрать миллисекунды
|
||
std::time_t utime = curTime.tv_sec;
|
||
|
||
//Время в заданом формате
|
||
char buffer[80]; memset(buffer,0,sizeof(buffer));
|
||
//std::strftime(buffer,sizeof(buffer),"%Y.%m.%d %H:%M:%S",std::localtime(&utime));
|
||
std::strftime(buffer,sizeof(buffer),"%Y.%m.%d %H:%M:%S",std::localtime(&utime));
|
||
std::string time=buffer;
|
||
time+=":"+intToString(milli); //Добавляю миллисекунды
|
||
|
||
if(cout)
|
||
std::cout << "[" << time << "] " << data << std::endl; //Повтор лога в консоль
|
||
|
||
myfile << "[" << time << "] " << data << std::endl;
|
||
myfile.flush();
|
||
myfile.close();
|
||
result=true;
|
||
}else
|
||
{
|
||
std::cerr << "Logrotate error: " << strerror(errno) << " fileName: " << fileName << std::endl;
|
||
}
|
||
return result;
|
||
}*/
|
||
//---------------------------------------------------------------------------
|
||
std::string escape_json(const std::string& input) {
|
||
std::ostringstream oss;
|
||
for (char c : input) {
|
||
switch (c) {
|
||
case '"': oss << "\\\""; break;
|
||
case '\\': oss << "\\\\"; break;
|
||
case '\b': oss << "\\b"; break;
|
||
case '\f': oss << "\\f"; break;
|
||
case '\n': oss << "\\n"; break;
|
||
case '\r': oss << "\\r"; break;
|
||
case '\t': oss << "\\t"; break;
|
||
default:
|
||
if (static_cast<unsigned char>(c) < 0x20 || c == 0x7F) {
|
||
oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
|
||
} else {
|
||
oss << c;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return oss.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Сохранение лог файла по 10 мегабайт (в 2 файлика) Функция отрабатывает за 4 миллисекунды
|
||
bool logrotate(std::string fileName, std::string thread, std::string level, std::string data, bool cout, int size)
|
||
{
|
||
long fileSize = getFileSize(fileName);
|
||
//Переименовываем файл если он привысил размер
|
||
if(fileSize>1024*1024* size)
|
||
{
|
||
remove(std::string(fileName + ".1").c_str()); //Пытаюсь удалить старый файл
|
||
rename(fileName.c_str(),std::string(fileName+".1").c_str());
|
||
}
|
||
|
||
//Записываем лог
|
||
std::ofstream myfile(fileName.c_str(), std::ofstream::binary | std::fstream::app);
|
||
if (myfile.is_open())
|
||
{
|
||
std::stringstream str(std::stringstream::out | std::stringstream::binary);
|
||
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
|
||
SYSTEMTIME st;
|
||
GetLocalTime(&st);
|
||
char buffer[256];
|
||
memset(buffer, 0, sizeof(buffer));
|
||
sprintf(buffer,
|
||
"%d-%02d-%02d %02d:%02d:%02d.%03d",
|
||
st.wYear,
|
||
st.wMonth,
|
||
st.wDay,
|
||
st.wHour,
|
||
st.wMinute,
|
||
st.wSecond,
|
||
st.wMilliseconds);
|
||
str << "[" << buffer << "] " << data << std::endl;
|
||
#else
|
||
timeval curTime;
|
||
gettimeofday(&curTime, NULL);
|
||
int milli = curTime.tv_usec / 1000;
|
||
std::time_t utime = curTime.tv_sec;
|
||
char buffer[80]; memset(buffer, 0, sizeof(buffer));
|
||
std::strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", std::localtime(&utime));
|
||
str << "{\"timestamp\":\"" << buffer << "." << std::setw(3) << std::setfill('0') << milli << "Z\", \"thread\":\"" <<thread<<"\", \"level\":\""<<level<<"\", \"message\":\"" << escape_json(data)<<"\"}" << std::endl;
|
||
#endif
|
||
if (cout)
|
||
std::cout << "[" << buffer << "] " << data << std::endl; //Повтор лога в консоль
|
||
|
||
myfile.write(str.str().c_str(), str.str().length());
|
||
myfile.flush();
|
||
myfile.close();
|
||
return true;
|
||
}else
|
||
{
|
||
std::cerr << "Error: " << strerror(errno) << " " << fileName << std::endl;
|
||
}
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string charToHex(unsigned char c)
|
||
{
|
||
short i = c;
|
||
std::stringstream s;
|
||
s << std::setw(2) << std::setfill('0') << std::hex << i;
|
||
std::string result=s.str();
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string shortToHex(unsigned short c)
|
||
{
|
||
std::stringstream s;
|
||
s << std::setw(4) << std::setfill('0') << std::hex << c;
|
||
return s.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string uintToHex(unsigned int val,char size){
|
||
std::stringstream s;
|
||
s << std::setw(size) << std::setfill('0') << std::hex << val;
|
||
return s.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
unsigned char hexToChar(const std::string &str) {
|
||
short c = 0;
|
||
|
||
if(!str.empty()) {
|
||
std::istringstream in(str);
|
||
|
||
in >> std::hex >> c;
|
||
|
||
//if(in.fail()) {
|
||
// throw std::runtime_error("stream decode failure");
|
||
//}
|
||
}
|
||
return static_cast<unsigned char>(c);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Преобразовать строку битов в char
|
||
unsigned char bitStrToChar(std::string str)
|
||
{
|
||
unsigned char result=0;
|
||
int s=str.size();
|
||
for(int i=0;i<std::min(8,s);i++)
|
||
{
|
||
result=setBitVal(0,7-i,result);
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool hexStrToArray(const std::string &str,char* arr)
|
||
{
|
||
short c;
|
||
if(str.size()==0 || (str.size() % 2) > 0) return false;
|
||
for(size_t i=0;i<str.size()/2;i++)
|
||
{
|
||
std::istringstream in(str.substr(i*2,2));
|
||
in >> std::hex >> c;
|
||
if(in.fail()) return false;
|
||
arr[i] = c;
|
||
}
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool arrayToHexStr(char* arr,unsigned int len,std::string &str)
|
||
{
|
||
for(unsigned int i=0;i<len;i++)
|
||
{
|
||
str+=charToHex(arr[i]);
|
||
}
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool vectorToHexStr(std::vector < unsigned char >& arr,std::string &str)
|
||
{
|
||
for (unsigned int i = 0; i < arr.size(); i++)
|
||
{
|
||
str+=charToHex(arr[i]);
|
||
}
|
||
return true;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Инициализируем ножку чтоб в неё можно записывать 0 или 1 как в файл
|
||
//Документация GPIO: http://www.avrfreaks.net/wiki/index.php/Documentation:Linux/GPIO
|
||
/*bool initPin(std::string pinnum)
|
||
{
|
||
bool result=true;
|
||
|
||
std::string path = "/sys/class/gpio/gpio"; //Чтобы не переинициализировать проверяем существование директории
|
||
path += pinnum;
|
||
DIR* dir = opendir(path.c_str());
|
||
if (dir)
|
||
{
|
||
closedir(dir);
|
||
}else
|
||
{
|
||
FILE *fp;
|
||
char set_value[4] = {0,0,0,0};
|
||
if ((fp = fopen("/sys/class/gpio/export", "ab")) != NULL)
|
||
{
|
||
rewind(fp); //К началу файла
|
||
strcpy(set_value,pinnum.c_str());
|
||
fwrite(&set_value, sizeof(char), strlen(set_value), fp);
|
||
fclose(fp);
|
||
}else
|
||
result=false;
|
||
}
|
||
return result;
|
||
}*/
|
||
//---------------------------------------------------------------------------
|
||
//Задать направление чтения или записи (сейчас вывод) (A=0,B=32,C=64,D=96,E=128)
|
||
//dit=true на запись, dit=false на чтение, pull - подтяжка к 0 или к 1 питания.
|
||
/*bool setPinDir(std::string pinnum,bool dir=true)
|
||
{
|
||
bool result=true;
|
||
FILE *fp;
|
||
std::string fName = "/sys/class/gpio/gpio";
|
||
fName += pinnum;
|
||
fName += "/direction"; //Почемуто глючит когда плюсую в 1 строку (ответ от AT команд: повторы)
|
||
|
||
char set_value[5] = {0,0,0,0,0};
|
||
|
||
//проверяем нужно ли менять направление если нет ничего не делаем
|
||
if((fp = fopen(fName.c_str(), "r")) != NULL)
|
||
{
|
||
fread(set_value, 3, 1, fp);
|
||
fclose(fp);
|
||
}
|
||
|
||
if((dir && !(set_value[0]=='o' && set_value[1]=='u' && set_value[2]=='t')) || (!dir && !(set_value[0]=='i' && set_value[1]=='n')))
|
||
{
|
||
if ((fp = fopen(fName.c_str(), "rb+")) != NULL)
|
||
{
|
||
rewind(fp);
|
||
memset (set_value, 0, 5);
|
||
if(dir)
|
||
{
|
||
strcpy(set_value,"out");
|
||
fwrite(&set_value, sizeof(char), strlen(set_value), fp);
|
||
}else
|
||
{
|
||
strcpy(set_value,"in");
|
||
fwrite(&set_value, sizeof(char), strlen(set_value), fp);
|
||
memset (set_value, 0, 5);
|
||
}
|
||
fclose(fp);
|
||
} else
|
||
result=false;
|
||
}
|
||
return result;
|
||
}*/
|
||
//---------------------------------------------------------------------------
|
||
//Задаём напряжение для ножки (A=0,B=32,C=64,D=96,E=128)
|
||
bool setPinVal(std::string pinnum, bool val)
|
||
{
|
||
bool result=true;
|
||
FILE *fp;
|
||
std::string fName = "/sys/class/gpio/gpio";
|
||
fName += pinnum;
|
||
fName += "/value";
|
||
unsigned char ch;
|
||
if(val) ch='1'; else ch='0';
|
||
if ((fp = fopen(fName.c_str(), "wb+")) != NULL)
|
||
{
|
||
rewind(fp); //К началу файла
|
||
if(fwrite(&ch, sizeof(char), 1, fp)!=1) result=false;
|
||
fclose(fp);
|
||
}else
|
||
result=false;
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Получит напряжение ножки (A=0,B=32,C=64,D=96,E=128)
|
||
char getPinVal(std::string pinnum)
|
||
{
|
||
FILE *fp;
|
||
std::string fName= "/sys/class/gpio/gpio";
|
||
fName += pinnum;
|
||
fName += "/value";
|
||
char ch=-1;
|
||
|
||
fp = fopen(fName.c_str(), "r");
|
||
if (fp != NULL)
|
||
{
|
||
//rewind(fp); //К началу файла
|
||
if(fread (&ch, sizeof(char), 1, fp)!=1)
|
||
{
|
||
ch=-1; //Ошибка
|
||
}
|
||
fclose(fp);
|
||
}else
|
||
ch=-1;
|
||
|
||
if(ch=='0') return 0;
|
||
else if(ch=='1') return 1;
|
||
else return -1; //Ошибка
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string doubleToString(double val)
|
||
{
|
||
std::ostringstream strs;
|
||
strs << val;
|
||
return strs.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string intToString(int val)
|
||
{
|
||
std::stringstream ss;
|
||
ss << val;
|
||
return ss.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string uintToString(unsigned int val)
|
||
{
|
||
std::stringstream ss;
|
||
ss << val;
|
||
return ss.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string ullintToString(unsigned long long int val)
|
||
{
|
||
std::stringstream ss;
|
||
ss << val;
|
||
return ss.str();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string DecToBinStr(unsigned int N,int cnt){
|
||
std::string S="";
|
||
if(N!=0)
|
||
{
|
||
for(unsigned long i=1;i<sizeof(N)*8;i++)
|
||
{
|
||
if((N & 1) == 1) S="1"+S; else S="0"+S;
|
||
N=N >> 1;
|
||
}
|
||
S=S.substr(S.find("1"),S.size());
|
||
}
|
||
cnt-=S.size();
|
||
if(cnt>0){
|
||
for(int i=0;i<cnt;i++)
|
||
S="0"+S;
|
||
}
|
||
return S;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string addZero(std::string str,int count,char ch){
|
||
int val=std::min(count,(int)str.length());
|
||
return std::string(count - val, ch) + str;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string addZero(int val,int count,char ch){
|
||
return addZero(intToString(val),count,ch);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string DecToBinStr(int N,int cnt)
|
||
{
|
||
std::string S="";
|
||
if(N!=0)
|
||
{
|
||
for(unsigned long i=1;i<sizeof(N)*8;i++)
|
||
{
|
||
if((N & 1) == 1) S="1"+S; else S="0"+S;
|
||
N=N >> 1;
|
||
}
|
||
S=S.substr(S.find("1"),S.size());
|
||
}
|
||
cnt-=S.size();
|
||
if(cnt>0){
|
||
for(int i=0;i<cnt;i++)
|
||
S="0"+S;
|
||
}
|
||
return S;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string AfterFirst(std::string str,const char ch)
|
||
{
|
||
unsigned int pos=str.find(ch);
|
||
std::string result="";
|
||
result.append(str,pos+1,str.size());
|
||
return result;
|
||
}
|
||
|
||
//---------------------------------------------------------------------------
|
||
std::string BeforeFirst(std::string str,const unsigned char ch)
|
||
{
|
||
unsigned int pos=str.find(ch);
|
||
std::string result="";
|
||
result.append(str,0,pos);
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
///Получить строку до указанного символа если символа нет то вернет всю строку.
|
||
std::string BeforeLast(std::string str,char ch)
|
||
{
|
||
int pos=0;
|
||
for(unsigned int i=0;i<str.length();i++)
|
||
{
|
||
if(str[i]==ch) pos=i;
|
||
}
|
||
if(pos==0) pos=str.length();
|
||
|
||
std::string result="";
|
||
result.append(str,0,pos);
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Отрезать от строки до указанного символа если не найден символ отрезается вся строка
|
||
std::string CutBeforeFirst(std::string& str,const unsigned char ch)
|
||
{
|
||
int pos=str.find(ch);
|
||
std::string result="";
|
||
if(pos==-1)
|
||
{
|
||
result.append(str);
|
||
str.erase();
|
||
}else
|
||
{
|
||
result.append(str,0,pos);
|
||
str.erase(0,pos+1);
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string CutBeforeFirst(std::string& str,std::string br)
|
||
{
|
||
int pos=str.find(br);
|
||
std::string result="";
|
||
if(pos==-1)
|
||
{
|
||
result.append(str);
|
||
str.erase();
|
||
}else
|
||
{
|
||
result.append(str,0,pos);
|
||
str.erase(0,pos+br.length());
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Если не найдёт нужный символ то вернёт всю строку
|
||
std::string CutAfterLast(std::string& str,const unsigned char ch)
|
||
{
|
||
std::string result="";
|
||
size_t pos=str.find_last_of(ch);
|
||
if(pos!=std::string::npos)
|
||
{
|
||
result.append(str,pos+1,str.length()-pos-1);
|
||
str.erase(pos);
|
||
}else
|
||
{
|
||
result.append(str);
|
||
str.erase();
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
std::string CutAfterFirst(std::string& str,std::string br)
|
||
{
|
||
size_t pos=str.find(br);
|
||
std::string result="";
|
||
if(pos==std::string::npos)
|
||
{
|
||
result.append(str);
|
||
str.erase();
|
||
}else
|
||
{
|
||
result.append(str,pos + br.size(),str.length() - pos - br.size());
|
||
str.erase(pos);
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Всё после заданного разделителя, если разделитель не найден то сначала строки
|
||
std::string AfterLast(std::string str,const unsigned char ch)
|
||
{
|
||
int pos=str.find_last_of(ch)+1;
|
||
if(pos>=0)
|
||
{
|
||
int len=str.length()-pos;
|
||
return str.substr(pos,len);
|
||
}else
|
||
{
|
||
return str;
|
||
}
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
template<typename T>
|
||
T fromString(const std::string& s)
|
||
{
|
||
std::istringstream iss(s);
|
||
T res;
|
||
iss >> res;
|
||
return res;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
double StdStrToDouble(std::string& str)
|
||
{
|
||
if(str=="") return 0;
|
||
return fromString<double>(str);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
float StdStrToFloat(std::string& str)
|
||
{
|
||
if(str=="") return 0;
|
||
return fromString<float>(str);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Безопасное преобразование в float
|
||
bool StdStrToFloat(std::string& str,float& val)
|
||
{
|
||
if(str=="") { val = 0; return false; }
|
||
try
|
||
{
|
||
val = fromString<float>(str);
|
||
return true;
|
||
}catch(...)
|
||
{
|
||
val=0;
|
||
return false;
|
||
}
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
int StdStrToInt(std::string& str)
|
||
{
|
||
if(str=="") return 0;
|
||
return fromString<int>(str);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
unsigned int StdStrToUInt(std::string& str)
|
||
{
|
||
std::string tmp="";
|
||
for(int i=0;i<(int)str.length();i++)
|
||
if(str[i]=='0' || str[i]=='1' || str[i]=='2' || str[i]=='3' || str[i]=='4' || str[i]=='5' || str[i]=='6' || str[i]=='7' || str[i]=='8' || str[i]=='9') tmp+=str[i];
|
||
|
||
if(tmp=="") return 0;
|
||
return fromString<unsigned int>(tmp);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
unsigned long long StdStrToULLInt(std::string& str){
|
||
std::string tmp="";
|
||
for(int i=0;i<(int)str.length();i++)
|
||
if(str[i]=='0' || str[i]=='1' || str[i]=='2' || str[i]=='3' || str[i]=='4' || str[i]=='5' || str[i]=='6' || str[i]=='7' || str[i]=='8' || str[i]=='9') tmp+=str[i];
|
||
|
||
if(tmp=="") return 0;
|
||
return fromString<unsigned long long>(tmp);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
unsigned int HexStdStrToUInt(std::string& str)
|
||
{
|
||
unsigned int x;
|
||
std::stringstream ss;
|
||
ss << std::hex << str;
|
||
ss >> x;
|
||
return x;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Получить дату последнего изменения файла
|
||
long getFileDateModiff(std::string file)
|
||
{
|
||
#ifdef __linux__
|
||
struct stat fStat;
|
||
int rc = stat(file.c_str(), &fStat);
|
||
if(rc==0)
|
||
{
|
||
return fStat.st_mtim.tv_sec;
|
||
}
|
||
return 0;
|
||
#elif _WIN32
|
||
return 0;
|
||
#else
|
||
#endif
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
//удалить старые файлы которые были созданы больше заданного количества дней
|
||
bool deleteOldFiles(std::string path,int days)
|
||
{
|
||
bool result=true;
|
||
std::list<std::string> fileList;
|
||
UtilityW::GetFiles(fileList,path);
|
||
std::list<std::string>::const_iterator iterator;
|
||
for (iterator = fileList.begin(); iterator != fileList.end(); ++iterator) {
|
||
std::string fName = *iterator;
|
||
long timeS = getFileDateModiff(fName);
|
||
int tNow=std::time(NULL);
|
||
int tDiff = tNow-timeS;
|
||
if(tDiff > days*24*60*60) {
|
||
if(!deleteFile(fName)) {
|
||
result=result & false;
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
//Удалить самый старый файл в директории
|
||
bool deleteOldFile(std::string path)
|
||
{
|
||
bool result=true;
|
||
long timeOld = std::time(NULL);
|
||
std::string fNameOld = "";
|
||
std::list<std::string> fileList;
|
||
UtilityW::GetFiles(fileList,path);
|
||
std::list<std::string>::const_iterator iterator;
|
||
for (iterator = fileList.begin(); iterator != fileList.end(); ++iterator) {
|
||
std::string fName = *iterator;
|
||
long timeS = getFileDateModiff(fName);
|
||
if(timeOld>timeS){
|
||
timeOld=timeS;
|
||
fNameOld=fName;
|
||
}
|
||
}
|
||
if(fNameOld.length()>0){
|
||
if(!deleteFile(fNameOld)) {
|
||
result=false;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//Прочитать файл в память (закоментил, проверка на ИБ)
|
||
// data - куда будем писать, разанее нужно создать
|
||
/*int readFile(std::string file, char* data, int size)
|
||
{
|
||
ssize_t bytes_read = 0;
|
||
FILE *ptr;
|
||
if((ptr = fopen(file.c_str(),"rb")) != NULL)
|
||
{
|
||
while(!feof(ptr) && !ferror(ptr))
|
||
{
|
||
ssize_t read = fread(data, 1, size, ptr);
|
||
data = data + read;
|
||
bytes_read+=read;
|
||
}
|
||
fclose(ptr);
|
||
}
|
||
return bytes_read;
|
||
}*/
|
||
//---------------------------------------------------------------------------
|
||
bool dirExists(std::string path)
|
||
{
|
||
struct stat info;
|
||
|
||
if(stat( path.c_str(), &info ) != 0)
|
||
return 0;
|
||
else if(info.st_mode & S_IFDIR)
|
||
return 1;
|
||
else
|
||
return 0;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
bool fileExists(std::string name)
|
||
{
|
||
if (FILE *file = fopen(name.c_str(), "r")) {
|
||
fclose(file);
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
void delString(std::vector<std::string> *mas, int pos)
|
||
{
|
||
int size = (int)mas->size();
|
||
if(pos<size)
|
||
mas->erase(mas->begin()+pos);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//time - время в секундах с милисекундами в дробной
|
||
std::string unixTimeToDate(double time)
|
||
{
|
||
#ifdef __linux__
|
||
struct tm * dt;
|
||
char b[20];
|
||
memset(b,0,20);
|
||
|
||
time_t tmp1=floor(time);
|
||
unsigned short tmp2 = (time - tmp1) * 1000;
|
||
|
||
dt = localtime(&tmp1);
|
||
strftime(b, sizeof(b), "%Y.%m.%d %H:%M:%S", dt);
|
||
|
||
std::string result=b;
|
||
if(tmp2!=0)
|
||
{
|
||
result += '.';
|
||
result += intToString(tmp2);
|
||
}
|
||
return result;
|
||
#elif _WIN32
|
||
return "";
|
||
#else
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
//В секундах
|
||
void sleep2(int sec)
|
||
{
|
||
#ifdef __linux__
|
||
sleep(sec);
|
||
#elif _WIN32
|
||
Sleep(sec*1000);
|
||
#else
|
||
#endif
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
void TrimLeft(std::string& str)
|
||
{
|
||
size_t startpos = str.find_first_not_of(" \t\f\n\r");
|
||
if(startpos != std::string::npos)
|
||
{
|
||
str = str.substr( startpos );
|
||
}else
|
||
{
|
||
str.clear(); //Вся строка из спец символов
|
||
}
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
void TrimRight(std::string& str)
|
||
{
|
||
std::string::size_type endpos = str.find_last_not_of(" \t\f\n\r");
|
||
if( endpos != std::string::npos )
|
||
{
|
||
str = str.substr( 0, endpos+1 );
|
||
}else
|
||
{
|
||
str.clear(); //Вся строка из спец символов
|
||
}
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
void Trim(std::string& s)
|
||
{
|
||
TrimLeft(s);
|
||
TrimRight(s);
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
//Для определения проходит ли линия в нутри заданого радиуса
|
||
//r - радиус
|
||
//cx,cy - центр радиуса
|
||
//lx1, ly1 - начало линии
|
||
//lx2, ly2 - конец линии
|
||
//Coincides - Проходит или нет
|
||
//x, y - Ближайшая точка на линии к центру радиуса
|
||
void Distance(float r, float cx, float cy, float lx1, float ly1, float lx2, float ly2, bool& Coincides, float& x, float& y)
|
||
{
|
||
double ang, angcos, angsin;
|
||
double ncx, ncy, nlx2, nr;
|
||
|
||
x = 0.0; y = 0.0;
|
||
|
||
cx = cx - lx1;
|
||
cy = cy - ly1;
|
||
lx2 = lx2 - lx1;
|
||
ly2 = ly2 - ly1;
|
||
ang = atan(ly2 / lx2);
|
||
if (lx2<0) ang = ang + M_PI;
|
||
if ((lx2>0) && (ly2<0)) ang = ang + (2 * M_PI);
|
||
angcos = cos(ang);
|
||
angsin = sin(ang);
|
||
ncx = cx*angcos + cy*angsin;
|
||
ncy = cy*angcos - (cx*angsin);
|
||
nlx2 = lx2*angcos + ly2*angsin;
|
||
nr = fabs(ncy);
|
||
Coincides = false;
|
||
if (nr<r)
|
||
{
|
||
Coincides = true;
|
||
if (ncx<0)
|
||
{
|
||
if (ncx<-r)
|
||
{
|
||
Coincides = false;
|
||
return;
|
||
}
|
||
nr = sqrt(ncx*ncx + ncy*ncy);
|
||
if (nr<r)
|
||
{
|
||
x = lx1;
|
||
y = ly1;
|
||
return;
|
||
}
|
||
Coincides = false;
|
||
return;
|
||
}
|
||
else
|
||
if (ncx>nlx2)
|
||
{
|
||
if (ncx>nlx2 + r)
|
||
{
|
||
Coincides = false;
|
||
return;
|
||
}
|
||
nr = sqrt((ncx - nlx2)*(ncx - nlx2) + ncy*ncy);
|
||
if (nr<r)
|
||
{
|
||
x = lx2 + lx1;
|
||
y = ly2 + ly1;
|
||
return;
|
||
}
|
||
Coincides = false;
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
angcos = cos(2 * M_PI - ang);
|
||
angsin = sin(2 * M_PI - ang);
|
||
x = (float)(ncx*angcos + lx1);
|
||
y = (float)(-(ncx*angsin) + ly1);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
bool parseGPRMC(std::string ans,time_t& utime,double& lon,double& lat,float& speed,float& angle)
|
||
{
|
||
#ifdef __linux__
|
||
bool result=false;
|
||
std::string time; //Время «hh» — часы, «mm» — минуты, «ss.sss» — секунды. Длина дробной части секунд варьируется.
|
||
std::string date; //Дата «ddmmyy» ведущие нули обязательны
|
||
|
||
UtilityW::Trim(ans);
|
||
if(ans!="")
|
||
{
|
||
if(ans.find("$GPRMC")==0) //Recommended minimum specific GPS/Transit data см. https://ru.wikipedia.org/wiki/NMEA_0183 (Берётся с UBLOX 6)
|
||
{
|
||
//Пример пакета: $GPRMC,074353.0,A,4315.286297,N,07651.391112,E,0.0,255.3,191214,,,A*68
|
||
try
|
||
{
|
||
std::string stmp1="",stmp2=""; //Временные строки
|
||
//Подсчитываем контрольную сумму
|
||
unsigned char csum=0;
|
||
for(int i=1;i<(int)ans.length();i++)
|
||
{ if(ans[i]=='*') break;
|
||
csum = csum ^ ans[i];
|
||
}
|
||
stmp1=UtilityW::AfterLast(ans,'*');
|
||
if(csum==UtilityW::HexStdStrToUInt(stmp1)) //Проверяем контрольную сумму
|
||
{
|
||
UtilityW::CutBeforeFirst(ans,','); //Удаляем $GPRMC,
|
||
std::string time = UtilityW::CutBeforeFirst(ans,','); //Время фиксации местоположения по Всемирному координированному времени UTC: «hh» — часы, «mm» — минуты, «ss.sss» — секунды. Длина дробной части секунд варьируется. Лидирующие нули не опускаются.
|
||
if(UtilityW::CutBeforeFirst(ans,',')=="A") //Если данные достоверны
|
||
{
|
||
stmp2 = UtilityW::CutBeforeFirst(ans,','); //«GGMM.MM» — широта. 2 цифры градусов(«GG»), 2 цифры целых минут, точка и дробная часть минут переменной длины. Лидирующие нули не опускаются.
|
||
if(stmp2.length()>0)
|
||
{
|
||
stmp1=stmp2.substr(0,2); stmp2=stmp2.substr(2);
|
||
lat = UtilityW::StdStrToDouble(stmp1);
|
||
lat += UtilityW::StdStrToDouble(stmp2) / 60.0f;
|
||
}else
|
||
lat = 0;
|
||
|
||
if(UtilityW::CutBeforeFirst(ans,',')=="S") lat=-lat; //«P» — «N» для северной или «S» для южной широты.
|
||
|
||
stmp2 = UtilityW::CutBeforeFirst(ans,','); //«gggmm.mm» — долгота. 3 цифры градусов(«ggg»), 2 цифры целых минут, точка и дробная часть минут переменной длины. Лидирующие нули не опускаются.
|
||
if(stmp2.length()>0)
|
||
{
|
||
stmp1=stmp2.substr(0,3); stmp2=stmp2.substr(3);
|
||
lon = UtilityW::StdStrToDouble(stmp1);
|
||
lon += UtilityW::StdStrToDouble(stmp2) / 60.0f;
|
||
}else
|
||
lon = 0;
|
||
|
||
if(UtilityW::CutBeforeFirst(ans,',')=="W") lon=-lon; //«J» — «E» для восточной или «W» для западной долготы.
|
||
|
||
stmp1 = UtilityW::CutBeforeFirst(ans,','); // горизонтальная составляющая скорости относительно земли в узлах.
|
||
speed = UtilityW::StdStrToFloat(stmp1);
|
||
stmp1 = UtilityW::CutBeforeFirst(ans,','); //путевой угол (направление скорости) в градусах.
|
||
angle = UtilityW::StdStrToFloat(stmp1);
|
||
std::string date = UtilityW::CutBeforeFirst(ans,','); //«ddmmyy» — дата: день месяца, месяц, последние 2 цифры года (ведущие нули обязательны).
|
||
|
||
//Преобразую время в UnixTime
|
||
utime = 0;
|
||
if(date!="" && time!="")
|
||
{
|
||
time=UtilityW::BeforeFirst(time,'.');
|
||
std::string date_time = date + " " + time; //Формат: «ddmmyy hhmmss»
|
||
struct tm tmd;
|
||
memset(&tmd, 0, sizeof(struct tm));
|
||
if(strptime(date_time.c_str(), "%d%m%y %H%M%S", &tmd))
|
||
{
|
||
utime = mktime(&tmd);
|
||
}
|
||
}
|
||
result=true;
|
||
}
|
||
}
|
||
}catch(...)
|
||
{}
|
||
}
|
||
}
|
||
return result;
|
||
#elif _WIN32
|
||
return false;
|
||
#else
|
||
#endif
|
||
}
|
||
|
||
}
|