Files
Tools_CPP/lib/utility.cpp
2024-11-01 12:23:13 +05:00

1451 lines
44 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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
}
}