1.修改了海阳光学光谱仪派生类,以支持暗像素信息的获取。
2.针对FLAME设备添加了新的实时暗背景扣除函数。 3.修改了部分系统执行逻辑,以支持FLAME的正确运行。
This commit is contained in:
Binary file not shown.
Binary file not shown.
@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
"DevContainersInfoBarHidden": true,
|
||||||
|
"ActiveTargetSystem": "172.16.0.83",
|
||||||
"OutputFoldersPerTargetSystem": {
|
"OutputFoldersPerTargetSystem": {
|
||||||
"本地计算机": [
|
"本地计算机": [
|
||||||
"out\\build\\Linux-GCC-Debug",
|
"out\\build\\Linux-GCC-Debug",
|
||||||
@ -7,6 +9,22 @@
|
|||||||
"out\\install\\x64-Debug",
|
"out\\install\\x64-Debug",
|
||||||
"out\\build\\Linux-GCC-Debug-Nanopi-Air",
|
"out\\build\\Linux-GCC-Debug-Nanopi-Air",
|
||||||
"out\\install\\Linux-GCC-Debug-Nanopi-Air"
|
"out\\install\\Linux-GCC-Debug-Nanopi-Air"
|
||||||
|
],
|
||||||
|
"172.16.0.74": [
|
||||||
|
"out\\build\\Linux-GCC-Debug",
|
||||||
|
"out\\install\\Linux-GCC-Debug",
|
||||||
|
"out\\build\\x64-Debug",
|
||||||
|
"out\\install\\x64-Debug",
|
||||||
|
"out\\build\\Linux-GCC-Debug-Nanopi-Air",
|
||||||
|
"out\\install\\Linux-GCC-Debug-Nanopi-Air"
|
||||||
|
],
|
||||||
|
"172.16.0.83": [
|
||||||
|
"out\\build\\Linux-GCC-Debug",
|
||||||
|
"out\\install\\Linux-GCC-Debug",
|
||||||
|
"out\\build\\x64-Debug",
|
||||||
|
"out\\install\\x64-Debug",
|
||||||
|
"out\\build\\Linux-GCC-Debug-Nanopi-Air",
|
||||||
|
"out\\install\\Linux-GCC-Debug-Nanopi-Air"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ExpandedNodes": [
|
"ExpandedNodes": [
|
||||||
@ -21,6 +39,6 @@
|
|||||||
"\\Source\\Settings",
|
"\\Source\\Settings",
|
||||||
"\\Source\\ZZ_SDK"
|
"\\Source\\ZZ_SDK"
|
||||||
],
|
],
|
||||||
"SelectedNode": "\\CMakeLists.txt",
|
"SelectedNode": "\\Source\\FS\\DataFileProcessor.cpp",
|
||||||
"PreviewInSolutionExplorer": false
|
"PreviewInSolutionExplorer": false
|
||||||
}
|
}
|
BIN
.vs/cmake.db
BIN
.vs/cmake.db
Binary file not shown.
BIN
.vs/slnx.sqlite
BIN
.vs/slnx.sqlite
Binary file not shown.
@ -5,6 +5,10 @@ cmake_minimum_required (VERSION 3.5)
|
|||||||
|
|
||||||
project ("IRIS_FODIS")
|
project ("IRIS_FODIS")
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
|
set(CMAKE_PREFIX_PATH "D:/Qt/Qt5.14.2/5.14.2/msvc2017_64/" ${CMAKE_PREFIX_PATH})
|
||||||
|
ENDIF ()
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
@ -10,25 +10,26 @@
|
|||||||
"ctestCommandArgs": "",
|
"ctestCommandArgs": "",
|
||||||
"inheritEnvironments": [ "linux_arm" ],
|
"inheritEnvironments": [ "linux_arm" ],
|
||||||
"intelliSenseMode": "linux-gcc-arm",
|
"intelliSenseMode": "linux-gcc-arm",
|
||||||
"remoteMachineName": "-237651717;172.16.0.93 (username=root, port=22, authentication=Password)",
|
"remoteMachineName": "-196451390;172.16.0.113 (username=root, port=22, authentication=Password)",
|
||||||
"remoteCMakeListsRoot": "/home/pi/FODIS/src/",
|
"remoteCMakeListsRoot": "/home/pi/FODIS/src/",
|
||||||
"remoteBuildRoot": "/home/pi/FODIS/build_d/${name}",
|
"remoteBuildRoot": "/home/pi/FODIS/build_d/${name}",
|
||||||
"remoteInstallRoot": "/home/pi/FODIS/out/install/${name}",
|
"remoteInstallRoot": "/home/pi/FODIS/out/install/${name}",
|
||||||
"remoteCopySources": true,
|
"remoteCopySources": true,
|
||||||
"rsyncCommandArgs": "-t --delete --delete-excluded",
|
"rsyncCommandArgs": "-t --delete --delete-excluded",
|
||||||
"remoteCopyBuildOutput": true,
|
"remoteCopyBuildOutput": true,
|
||||||
"remoteCopySourcesMethod": "sftp"
|
"remoteCopySourcesMethod": "rsync"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "x64-Debug",
|
"name": "x64-Debug",
|
||||||
"generator": "Ninja",
|
"generator": "Visual Studio 17 2022 Win64",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
"cmakeCommandArgs": "",
|
"cmakeCommandArgs": "",
|
||||||
"buildCommandArgs": "",
|
"buildCommandArgs": "",
|
||||||
"ctestCommandArgs": "",
|
"ctestCommandArgs": "",
|
||||||
"inheritEnvironments": [ "msvc_x64_x64" ]
|
"inheritEnvironments": [ "msvc_x64" ],
|
||||||
|
"intelliSenseMode": "windows-msvc-x64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Linux-GCC-Debug-Nanopi-Air",
|
"name": "Linux-GCC-Debug-Nanopi-Air",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[FS]
|
[FS]
|
||||||
Model=IS1
|
Model=IS1
|
||||||
Port=/dev/ttyUSB0
|
Port=/dev/ttyUSB0
|
||||||
UID=FLMS15815
|
UID=FLMS15814
|
||||||
Depth=65535
|
Depth=65535
|
||||||
AEMax=0.85
|
AEMax=0.85
|
||||||
AEMin=0.60
|
AEMin=0.60
|
||||||
|
11
Settings/DeviceSettings_IS11.ini
Normal file
11
Settings/DeviceSettings_IS11.ini
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[FS]
|
||||||
|
Model=IS11
|
||||||
|
Port=/dev/ttyUSB0
|
||||||
|
UID=
|
||||||
|
Depth=65535
|
||||||
|
AEMax=0.85
|
||||||
|
AEMin=0.60
|
||||||
|
MinSI=1000
|
||||||
|
[GPS]
|
||||||
|
Port=/dev/ttyS1
|
||||||
|
Baud=9600
|
@ -35,6 +35,7 @@ int CAbsFSController::Initialize()
|
|||||||
printf("Flame Not Opened");
|
printf("Flame Not Opened");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
GetDarkPixelIndices();
|
||||||
break;
|
break;
|
||||||
case DeviceModel::OSIFAlpha:
|
case DeviceModel::OSIFAlpha:
|
||||||
m_pFSCtrl = new OceanOptics_lib;
|
m_pFSCtrl = new OceanOptics_lib;
|
||||||
@ -400,6 +401,27 @@ int CAbsFSController::CheckAndAdjust_Fast()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CAbsFSController::GetDarkPixelIndices()
|
||||||
|
{
|
||||||
|
m_vecDarkPixleIndices.clear();
|
||||||
|
|
||||||
|
if (m_struFSParam.ucDeviceModel == DeviceModel::FLAME)
|
||||||
|
{
|
||||||
|
m_vecDarkPixleIndices = ((OceanOptics_lib*)m_pFSCtrl)->m_vecDarkPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////debug only
|
||||||
|
/*qDebug() << m_vecDarkPixleIndices.size();
|
||||||
|
qDebug() << ((OceanOptics_lib*)m_pFSCtrl)->m_vecDarkPixels.size();
|
||||||
|
for (int i=0;i< m_vecDarkPixleIndices.size();i++)
|
||||||
|
{
|
||||||
|
qDebug() << m_vecDarkPixleIndices[i];
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////debug only
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void CAbsFSController::GetDeviceAttr(DeviceAttribute& struDeviceAttr)
|
void CAbsFSController::GetDeviceAttr(DeviceAttribute& struDeviceAttr)
|
||||||
{
|
{
|
||||||
struDeviceAttr = m_struDeviceAttr;
|
struDeviceAttr = m_struDeviceAttr;
|
||||||
|
@ -29,15 +29,19 @@ public:
|
|||||||
int PerformAutoExposure();
|
int PerformAutoExposure();
|
||||||
int CheckAndAdjust_Fast();
|
int CheckAndAdjust_Fast();
|
||||||
|
|
||||||
|
int GetDarkPixelIndices();
|
||||||
|
|
||||||
void GetDeviceAttr(DeviceAttribute &struDeviceAttr);
|
void GetDeviceAttr(DeviceAttribute &struDeviceAttr);
|
||||||
public:
|
public:
|
||||||
std::atomic_int m_iFlagInit;
|
std::atomic_int m_iFlagInit;
|
||||||
|
std::vector<int> m_vecDarkPixleIndices;
|
||||||
|
DeviceAttribute m_struDeviceAttr;
|
||||||
private:
|
private:
|
||||||
DeviceAttribute m_struDeviceAttr;
|
|
||||||
CIrisFSBase* m_pFSCtrl;
|
CIrisFSBase* m_pFSCtrl;
|
||||||
OneFSContext m_struFSParam;
|
OneFSContext m_struFSParam;
|
||||||
DataFrame m_struSingleFrame;
|
DataFrame m_struSingleFrame;
|
||||||
QString m_qstrWaveLengthPath;
|
QString m_qstrWaveLengthPath;
|
||||||
private:
|
private:
|
||||||
//int CreateWavelengthFile();
|
//int CreateWavelengthFile();
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -81,12 +81,18 @@ int CMainGrabber::Initialize_Self()
|
|||||||
{
|
{
|
||||||
InitializeWorkers();
|
InitializeWorkers();
|
||||||
SetupMsgPipelines();
|
SetupMsgPipelines();
|
||||||
LoadDCT();
|
if (m_struFSRunParams.ucDeviceModel== DeviceModel::FLAME)
|
||||||
|
{
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadDCT();
|
||||||
|
}
|
||||||
|
|
||||||
emit Signal_InitFinished();
|
emit Signal_InitFinished();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainGrabber::Delay_MSec(ZZ_U16 usMS)
|
void CMainGrabber::Delay_MSec(ZZ_U16 usMS)
|
||||||
{
|
{
|
||||||
@ -114,6 +120,12 @@ int CMainGrabber::InitializeWorkers()
|
|||||||
}
|
}
|
||||||
m_pctrlFS->GetDeviceAttr(m_struDeviceAttr);
|
m_pctrlFS->GetDeviceAttr(m_struDeviceAttr);
|
||||||
m_dfpDataSaver->WriteWavelengthInfo(m_struDeviceAttr.fWaveLengthInNM, m_struDeviceAttr.iPixels);
|
m_dfpDataSaver->WriteWavelengthInfo(m_struDeviceAttr.fWaveLengthInNM, m_struDeviceAttr.iPixels);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////20230713
|
||||||
|
if (m_struFSRunParams.dMinSamplingInterval < m_pctrlFS->m_struDeviceAttr.iMaxIntegrationTimeInMS)
|
||||||
|
{
|
||||||
|
m_pctrlFS->m_struDeviceAttr.iMaxIntegrationTimeInMS = m_struFSRunParams.dMinSamplingInterval * 2;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,45 +214,65 @@ int CMainGrabber::CheckExposureTime(DataFrame dfTemp)
|
|||||||
|
|
||||||
int CMainGrabber::RemoveBackground(DataFrame& dfTemp)
|
int CMainGrabber::RemoveBackground(DataFrame& dfTemp)
|
||||||
{
|
{
|
||||||
int iA = dfTemp.usExposureTimeInMS / 10;
|
if (m_struFSRunParams.ucDeviceModel==DeviceModel::FLAME)
|
||||||
int iB = dfTemp.usExposureTimeInMS % 10;
|
|
||||||
|
|
||||||
qDebug() << "iA" << iA;
|
|
||||||
qDebug() << "iB" << iB;
|
|
||||||
|
|
||||||
if (iA == 0)
|
|
||||||
{
|
{
|
||||||
m_dfBackground = m_vecDataFrame[iB];
|
double dBackground = 0;
|
||||||
|
for (int i=0;i< m_pctrlFS->m_vecDarkPixleIndices.size();i++)
|
||||||
|
{
|
||||||
|
dBackground += dfTemp.lData[m_pctrlFS->m_vecDarkPixleIndices[i]];
|
||||||
|
}
|
||||||
|
dBackground = dBackground / m_pctrlFS->m_vecDarkPixleIndices.size();
|
||||||
|
|
||||||
|
for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
|
||||||
|
{
|
||||||
|
dfTemp.lData[i] = dfTemp.lData[i] - dBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "FLAME Real Time Background" << dBackground;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (iA>100)
|
int iA = dfTemp.usExposureTimeInMS / 10;
|
||||||
|
int iB = dfTemp.usExposureTimeInMS % 10;
|
||||||
|
|
||||||
|
qDebug() << "iA" << iA;
|
||||||
|
qDebug() << "iB" << iB;
|
||||||
|
|
||||||
|
if (iA == 0)
|
||||||
{
|
{
|
||||||
m_dfBackground = m_vecDataFrame[m_vecDataFrame.size()-1];
|
m_dfBackground = m_vecDataFrame[iB-1];
|
||||||
}
|
|
||||||
else if(iA<=9&&iA>=1)
|
|
||||||
{
|
|
||||||
m_dfBackground = m_vecDataFrame[8 + iA];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int iAA= dfTemp.usExposureTimeInMS / 100;
|
if (iA > 100)
|
||||||
int iBB= dfTemp.usExposureTimeInMS % 100;
|
|
||||||
|
|
||||||
DataFrame dfTempX1, dfTempX2;
|
|
||||||
dfTempX1 = m_vecDataFrame[17 + iAA];
|
|
||||||
dfTempX2 = m_vecDataFrame[18 + iAA];
|
|
||||||
|
|
||||||
for (int i=0;i< m_struDeviceAttr.iPixels;i++)
|
|
||||||
{
|
{
|
||||||
m_dfBackground.lData[i] = dfTempX1.lData[i] + (dfTempX2.lData[i] - dfTempX1.lData[i]) * (double)iBB / (double)100;
|
m_dfBackground = m_vecDataFrame[m_vecDataFrame.size() - 1];
|
||||||
|
}
|
||||||
|
else if (iA <= 9 && iA >= 1)
|
||||||
|
{
|
||||||
|
m_dfBackground = m_vecDataFrame[8 + iA];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int iAA = dfTemp.usExposureTimeInMS / 100;
|
||||||
|
int iBB = dfTemp.usExposureTimeInMS % 100;
|
||||||
|
|
||||||
|
DataFrame dfTempX1, dfTempX2;
|
||||||
|
dfTempX1 = m_vecDataFrame[17 + iAA];
|
||||||
|
dfTempX2 = m_vecDataFrame[18 + iAA];
|
||||||
|
|
||||||
|
for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
|
||||||
|
{
|
||||||
|
m_dfBackground.lData[i] = dfTempX1.lData[i] + (dfTempX2.lData[i] - dfTempX1.lData[i]) * (double)iBB / (double)100;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
|
for (int i = 0; i < m_struDeviceAttr.iPixels; i++)
|
||||||
{
|
{
|
||||||
dfTemp.lData[i] = dfTemp.lData[i] - m_dfBackground.lData[i];
|
dfTemp.lData[i] = dfTemp.lData[i] - m_dfBackground.lData[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -110,16 +110,121 @@ void DataFileProcessor::LoadSingleDataFile(QString qstrFileName)
|
|||||||
printf("LoadWaveLengthFile open Failed.");
|
printf("LoadWaveLengthFile open Failed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int iExpoTime=0;
|
||||||
|
std::vector<int> vecExpotime;
|
||||||
|
std::vector<double> vecDTime;
|
||||||
long long int llCount = (qfDataFile.size()) / (sizeof(DataFrame));
|
long long int llCount = (qfDataFile.size()) / (sizeof(DataFrame));
|
||||||
for (int i=0;i<llCount;i++)
|
for (int i=0;i<llCount;i++)
|
||||||
{
|
{
|
||||||
QByteArray qbDataFrame = qfDataFile.read(sizeof(DataFrame));
|
QByteArray qbDataFrame = qfDataFile.read(sizeof(DataFrame));
|
||||||
memcpy(&dfTemp, qbDataFrame, sizeof(DataFrame));
|
memcpy(&dfTemp, qbDataFrame, sizeof(DataFrame));
|
||||||
|
vecExpotime.push_back(dfTemp.usExposureTimeInMS);
|
||||||
|
vecDTime.push_back(dfTemp.dTimes);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DataFileProcessor::RecoverBackground(QString qstrDataFileName, QString qstrBackgroundFileName)
|
||||||
|
{
|
||||||
|
int iExpoTime = 0;
|
||||||
|
std::vector<int> vecExpotime;
|
||||||
|
std::vector<double> vecDTime;
|
||||||
|
DataFrame dfDataTemp;
|
||||||
|
DataFrame m_dfBackground;
|
||||||
|
|
||||||
|
QString qstrFullFileName(qstrDataFileName+"recv");
|
||||||
|
QFile qfDataRec(qstrFullFileName);
|
||||||
|
bool bRes = qfDataRec.open(QFile::WriteOnly | QIODevice::Append);
|
||||||
|
if (!bRes)
|
||||||
|
{
|
||||||
|
printf("WriteData QFile open Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile qfDataFile(qstrDataFileName);
|
||||||
|
bRes = qfDataFile.open(QFile::ReadOnly);
|
||||||
|
if (!bRes)
|
||||||
|
{
|
||||||
|
printf("qstrDataFileName open Failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
///
|
||||||
|
std::vector<DataFrame> m_vecDataFrame;
|
||||||
|
m_vecDataFrame.clear();
|
||||||
|
DataFrame dfDarkTemp;
|
||||||
|
|
||||||
|
QFile qfData(qstrBackgroundFileName);
|
||||||
|
bRes = qfData.open(QFile::ReadOnly);
|
||||||
|
if (!bRes)
|
||||||
|
{
|
||||||
|
//qDebug() << "LoadTable open Failed.";
|
||||||
|
printf("LoadTable open Failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString qstrTemp;
|
||||||
|
QStringList qsList;
|
||||||
|
while (!qfData.atEnd())
|
||||||
|
{
|
||||||
|
QString data;
|
||||||
|
data = qfData.readLine();
|
||||||
|
qsList = data.split(',');
|
||||||
|
|
||||||
|
dfDarkTemp.usExposureTimeInMS = qsList[0].toInt();
|
||||||
|
for (int i = 0; i < qsList.size() - 1; i++)
|
||||||
|
{
|
||||||
|
dfDarkTemp.lData[i] = qsList[i + 1].toInt();
|
||||||
|
qDebug() << qsList[i] << ";";
|
||||||
|
}
|
||||||
|
m_vecDataFrame.push_back(dfDarkTemp);
|
||||||
|
qDebug() << qsList.size() << endl;
|
||||||
|
}
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
long long int llCount = (qfDataFile.size()) / (sizeof(DataFrame));
|
||||||
|
for (int i = 0; i < llCount; i++)
|
||||||
|
{
|
||||||
|
QByteArray qbDataFrame = qfDataFile.read(sizeof(DataFrame));
|
||||||
|
memcpy(&dfDataTemp, qbDataFrame, sizeof(DataFrame));
|
||||||
|
vecExpotime.push_back(dfDataTemp.usExposureTimeInMS);
|
||||||
|
vecDTime.push_back(dfDataTemp.dTimes);
|
||||||
|
|
||||||
|
int iB = dfDataTemp.usExposureTimeInMS % 10;
|
||||||
|
|
||||||
|
m_dfBackground = m_vecDataFrame[iB];
|
||||||
|
|
||||||
|
for (int i = 0; i < 2048 ; i++)
|
||||||
|
{
|
||||||
|
dfDataTemp.lData[i] = dfDataTemp.lData[i] + m_dfBackground.lData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
double dBackground = 0;
|
||||||
|
int iCountBg = 0;
|
||||||
|
for (int i=6;i<21;i++)
|
||||||
|
{
|
||||||
|
dBackground = dBackground +dfDataTemp.lData[i];
|
||||||
|
iCountBg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dBackground = dBackground / iCountBg;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2048; i++)
|
||||||
|
{
|
||||||
|
dfDataTemp.lData[i] = dfDataTemp.lData[i] - dBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
qfDataRec.write((char*)&dfDataTemp, sizeof(DataFrame));
|
||||||
|
qfDataRec.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void DataFileProcessor::GenerateFilePath()
|
void DataFileProcessor::GenerateFilePath()
|
||||||
{
|
{
|
||||||
m_qdtTime = QDateTime::currentDateTime();
|
m_qdtTime = QDateTime::currentDateTime();
|
||||||
|
@ -18,6 +18,7 @@ public:
|
|||||||
|
|
||||||
void LoadWaveLengthFile(QString qstrFileName);
|
void LoadWaveLengthFile(QString qstrFileName);
|
||||||
void LoadSingleDataFile(QString qstrFileName);
|
void LoadSingleDataFile(QString qstrFileName);
|
||||||
|
void RecoverBackground(QString qstrDataFileName, QString qstrBackgroundFileName);
|
||||||
//void SetEnvironmentContex(EContext struEC);
|
//void SetEnvironmentContex(EContext struEC);
|
||||||
//void SetManmadeEnviromentalContext(MEContext struMEC);
|
//void SetManmadeEnviromentalContext(MEContext struMEC);
|
||||||
//void SetDeviceInfo(FSContext struDeviceContext);
|
//void SetDeviceInfo(FSContext struDeviceContext);
|
||||||
|
@ -69,6 +69,9 @@ int IS11_Ctrl_Qt::SingleShot(DataFrame& dfData)
|
|||||||
{
|
{
|
||||||
SendData_CMD03((char*)GET_ALL_DN, sizeof(GET_ALL_DN));
|
SendData_CMD03((char*)GET_ALL_DN, sizeof(GET_ALL_DN));
|
||||||
RecvData_CMD03(dfData);
|
RecvData_CMD03(dfData);
|
||||||
|
|
||||||
|
GetExposureTime(m_iExposureTime);
|
||||||
|
dfData.usExposureTimeInMS = (unsigned short)m_iExposureTime;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +96,7 @@ int IS11_Ctrl_Qt::GetExposureTime(int & iExposureTimeInMS)
|
|||||||
SendData_CMD03((char *)GET_INTEGRAL_TIME, sizeof(GET_INTEGRAL_TIME));
|
SendData_CMD03((char *)GET_INTEGRAL_TIME, sizeof(GET_INTEGRAL_TIME));
|
||||||
int iRes = RecvData_CMD03(qbaRecv);
|
int iRes = RecvData_CMD03(qbaRecv);
|
||||||
|
|
||||||
iExposureTimeInMS = qbaRecv[0]*256+ qbaRecv[1];
|
iExposureTimeInMS = ((unsigned char)(qbaRecv[0]))*256+ (unsigned char)(qbaRecv[1]);
|
||||||
return iRes;
|
return iRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,11 +265,11 @@ int IS11_Ctrl_Qt::RecvData_CMD03(QByteArray &qbaRecv)
|
|||||||
iRetryCount = 0;
|
iRetryCount = 0;
|
||||||
while (qbaOriRecv.size()< qbaOriRecv[2]+5)
|
while (qbaOriRecv.size()< qbaOriRecv[2]+5)
|
||||||
{
|
{
|
||||||
m_pSerialPort->waitForReadyRead(100);
|
m_pSerialPort->waitForReadyRead(1000);
|
||||||
Read_IS11(qbaTemp);
|
Read_IS11(qbaTemp);
|
||||||
qbaOriRecv.append(qbaTemp);
|
qbaOriRecv.append(qbaTemp);
|
||||||
iRetryCount++;
|
iRetryCount++;
|
||||||
if (iRetryCount > 20)
|
if (iRetryCount > 66)
|
||||||
{
|
{
|
||||||
qDebug() << "Recv Data Err.out of retry time";
|
qDebug() << "Recv Data Err.out of retry time";
|
||||||
return 2;
|
return 2;
|
||||||
@ -318,11 +321,11 @@ int IS11_Ctrl_Qt::RecvData_CMD03(DataFrame& dfData)
|
|||||||
qbaOriRecv.append(qbaTemp);
|
qbaOriRecv.append(qbaTemp);
|
||||||
while (qbaOriRecv.size() < 4 || ParseHdr(qbaOriRecv, 3) == 1)
|
while (qbaOriRecv.size() < 4 || ParseHdr(qbaOriRecv, 3) == 1)
|
||||||
{
|
{
|
||||||
m_pSerialPort->waitForReadyRead(100);
|
m_pSerialPort->waitForReadyRead(1000);
|
||||||
Read_IS11(qbaTemp);
|
Read_IS11(qbaTemp);
|
||||||
qbaOriRecv.append(qbaTemp);
|
qbaOriRecv.append(qbaTemp);
|
||||||
iRetryCount++;
|
iRetryCount++;
|
||||||
if (iRetryCount > 20)
|
if (iRetryCount > 66)
|
||||||
{
|
{
|
||||||
qDebug() << "Recv Hdr Err.out of retry time";
|
qDebug() << "Recv Hdr Err.out of retry time";
|
||||||
return 1;
|
return 1;
|
||||||
@ -333,11 +336,11 @@ int IS11_Ctrl_Qt::RecvData_CMD03(DataFrame& dfData)
|
|||||||
iRetryCount = 0;
|
iRetryCount = 0;
|
||||||
while (qbaOriRecv.size() < length + 4)
|
while (qbaOriRecv.size() < length + 4)
|
||||||
{
|
{
|
||||||
m_pSerialPort->waitForReadyRead(100);
|
m_pSerialPort->waitForReadyRead(1000);
|
||||||
Read_IS11(qbaTemp);
|
Read_IS11(qbaTemp);
|
||||||
qbaOriRecv.append(qbaTemp);
|
qbaOriRecv.append(qbaTemp);
|
||||||
iRetryCount++;
|
iRetryCount++;
|
||||||
if (iRetryCount > 20)
|
if (iRetryCount > 66)
|
||||||
{
|
{
|
||||||
qDebug() << "Recv Data Err.out of retry time";
|
qDebug() << "Recv Data Err.out of retry time";
|
||||||
return 2;
|
return 2;
|
||||||
@ -500,11 +503,11 @@ int IS11_Ctrl_Qt::RecvData_CMD06(QByteArray &qbaRecv)
|
|||||||
iRetryCount = 0;
|
iRetryCount = 0;
|
||||||
while (qbaOriRecv.size() < 8)
|
while (qbaOriRecv.size() < 8)
|
||||||
{
|
{
|
||||||
m_pSerialPort->waitForReadyRead(100);
|
m_pSerialPort->waitForReadyRead(1000);
|
||||||
Read_IS11(qbaTemp);
|
Read_IS11(qbaTemp);
|
||||||
qbaOriRecv.append(qbaTemp);
|
qbaOriRecv.append(qbaTemp);
|
||||||
iRetryCount++;
|
iRetryCount++;
|
||||||
if (iRetryCount > 20)
|
if (iRetryCount > 66)
|
||||||
{
|
{
|
||||||
qDebug() << "Recv Data Err.out of retry time";
|
qDebug() << "Recv Data Err.out of retry time";
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "pch.h"
|
||||||
#include "OControl_USB.h"
|
#include "OControl_USB.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -86,6 +87,27 @@ int OceanOptics_lib::Initialize(bool bIsUSBMode, std::string ucPortNumber, std::
|
|||||||
|
|
||||||
SetExposureTime(minimum_time / 1000);
|
SetExposureTime(minimum_time / 1000);
|
||||||
|
|
||||||
|
m_vecDarkPixels.clear();
|
||||||
|
int* piIndex = new int[64];
|
||||||
|
int iCount = seabreeze_get_electric_dark_pixel_indices(m_iSpectralmeterHandle, &error, piIndex, 64);
|
||||||
|
for (int i = 0; i < iCount; i++)
|
||||||
|
{
|
||||||
|
m_vecDarkPixels.push_back(piIndex[i]);
|
||||||
|
}
|
||||||
|
delete[] piIndex;
|
||||||
|
|
||||||
|
qDebug() << "from lib" << iCount;
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
/*CString cstrTemp, cstrTemp1;
|
||||||
|
for (int i=0;i< m_vecDarkPixels.size();i++)
|
||||||
|
{
|
||||||
|
cstrTemp1.Format(_T("%d"), m_vecDarkPixels[i]);
|
||||||
|
cstrTemp = cstrTemp+L"-"+cstrTemp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AfxMessageBox(cstrTemp);*/
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +168,27 @@ int OceanOptics_lib::Initialize()
|
|||||||
|
|
||||||
SetExposureTime(minimum_time / 1000);
|
SetExposureTime(minimum_time / 1000);
|
||||||
|
|
||||||
|
m_vecDarkPixels.clear();
|
||||||
|
int *piIndex=new int[64];
|
||||||
|
int iCount = seabreeze_get_electric_dark_pixel_indices(m_iSpectralmeterHandle,&error, piIndex,64);
|
||||||
|
for (int i=0;i< iCount;i++)
|
||||||
|
{
|
||||||
|
m_vecDarkPixels.push_back(piIndex[i]);
|
||||||
|
}
|
||||||
|
delete[] piIndex;
|
||||||
|
|
||||||
|
qDebug() << "from lib" << iCount;
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
/*CString cstrTemp, cstrTemp1;
|
||||||
|
for (int i=0;i< m_vecDarkPixels.size();i++)
|
||||||
|
{
|
||||||
|
cstrTemp1.Format(_T("%d"), m_vecDarkPixels[i]);
|
||||||
|
cstrTemp = cstrTemp+L"-"+cstrTemp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AfxMessageBox(cstrTemp);*/
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +329,7 @@ int OceanOptics_lib::SingleShot(DataFrame &dfData)
|
|||||||
|
|
||||||
for (int tmp = 0; tmp < spec_length; tmp++)
|
for (int tmp = 0; tmp < spec_length; tmp++)
|
||||||
{
|
{
|
||||||
dfData.lData[tmp] = spectrum[tmp];
|
dfData.lData[tmp] = (unsigned int)spectrum[tmp];
|
||||||
}
|
}
|
||||||
|
|
||||||
int exposureTimeInMS;
|
int exposureTimeInMS;
|
||||||
@ -416,7 +459,7 @@ int OceanOptics_lib::GetDeviceTemperature(float &fTemperature)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fTemperature = temp;
|
fTemperature = (float)temp;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -484,7 +527,7 @@ int OceanOptics_lib::GetDeviceAttribute(DeviceAttribute &Attr)
|
|||||||
|
|
||||||
for (int tmp = 0; tmp < spec_length; tmp++)
|
for (int tmp = 0; tmp < spec_length; tmp++)
|
||||||
{
|
{
|
||||||
Attr.fWaveLengthInNM[tmp] = wls[tmp];
|
Attr.fWaveLengthInNM[tmp] = (float)wls[tmp];
|
||||||
}
|
}
|
||||||
|
|
||||||
free(wls);
|
free(wls);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <vector>
|
||||||
#include "api/SeaBreezeWrapper.h"
|
#include "api/SeaBreezeWrapper.h"
|
||||||
#include "IrisFiberSpectrometerBase.h"
|
#include "IrisFiberSpectrometerBase.h"
|
||||||
|
|
||||||
@ -51,7 +52,8 @@ private:
|
|||||||
int m_iExposureTime;
|
int m_iExposureTime;
|
||||||
|
|
||||||
bool isSuccess(char* resultStr);
|
bool isSuccess(char* resultStr);
|
||||||
|
|
||||||
string GetDeviceType(int index);
|
string GetDeviceType(int index);
|
||||||
string GetSerialNumber(int index);
|
string GetSerialNumber(int index);
|
||||||
|
public:
|
||||||
|
std::vector<int> m_vecDarkPixels;
|
||||||
};
|
};
|
||||||
|
@ -41,6 +41,7 @@ int BD357Controller::SyncDateOnce()
|
|||||||
{
|
{
|
||||||
using namespace ZZ_MISCDEF;
|
using namespace ZZ_MISCDEF;
|
||||||
|
|
||||||
|
//bool bFlagFinish = 1;
|
||||||
bool bFlagFinish = false;
|
bool bFlagFinish = false;
|
||||||
size_t uiCount = 0;
|
size_t uiCount = 0;
|
||||||
//ZZ_U8 u8Rx,u8Tx;
|
//ZZ_U8 u8Rx,u8Tx;
|
||||||
@ -54,6 +55,7 @@ int BD357Controller::SyncDateOnce()
|
|||||||
{
|
{
|
||||||
m_pSerialPort->waitForReadyRead(1000);
|
m_pSerialPort->waitForReadyRead(1000);
|
||||||
m_qbReadData.append(m_pSerialPort->readAll());
|
m_qbReadData.append(m_pSerialPort->readAll());
|
||||||
|
qDebug() << "waiting for gps data..." << m_qbReadData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << m_qbReadData.size() << endl;
|
qDebug() << m_qbReadData.size() << endl;
|
||||||
@ -103,6 +105,7 @@ int BD357Controller::SyncDateOnce()
|
|||||||
}
|
}
|
||||||
//bFlagFinish = 1;
|
//bFlagFinish = 1;
|
||||||
}
|
}
|
||||||
|
qDebug() << "Signal_StartCapture emitted.";
|
||||||
emit Signal_StartCapture();
|
emit Signal_StartCapture();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -240,6 +243,7 @@ int BD357Controller::Slot_InitSelf()
|
|||||||
|
|
||||||
int BD357Controller::Slot_SyncDateOnce()
|
int BD357Controller::Slot_SyncDateOnce()
|
||||||
{
|
{
|
||||||
|
//emit Signal_StartCapture();
|
||||||
SyncDateOnce();
|
SyncDateOnce();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
114
main.cpp
114
main.cpp
@ -13,20 +13,19 @@ int main(int argc, char* argv[])
|
|||||||
using namespace ZZ_MISCDEF::ZZ_RUNPARAMS;
|
using namespace ZZ_MISCDEF::ZZ_RUNPARAMS;
|
||||||
using namespace ZZ_MISCDEF::MISC_DETECTOR;
|
using namespace ZZ_MISCDEF::MISC_DETECTOR;
|
||||||
|
|
||||||
//DataFrame aaaa;
|
|
||||||
//int xxxx = sizeof(aaaa);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QCoreApplication a(argc, argv);
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
QEventLoop qeLoop;
|
||||||
|
QTimer::singleShot(30000, &qeLoop, SLOT(quit()));
|
||||||
|
qeLoop.exec();
|
||||||
|
|
||||||
|
//ָʾ<D6B8>ƿ<EFBFBD><C6BF><EFBFBD>
|
||||||
system("gpio mode 4 out");
|
system("gpio mode 4 out");
|
||||||
system("gpio mode 5 out");
|
system("gpio mode 5 out");
|
||||||
|
|
||||||
qDebug() << "system(gpio mode 4 out)";
|
qDebug() << "system(gpio mode 4 out)";
|
||||||
qDebug() << "system(gpio mode 5 out)";//ָʾ<D6B8>ƿ<EFBFBD><C6BF><EFBFBD>
|
qDebug() << "system(gpio mode 5 out)";
|
||||||
bool bRes = false;
|
|
||||||
|
|
||||||
OneFSContext m_struFSParam;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
OneFSContext m_struFSParam;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
GPSInfo m_struGPSInfo;
|
GPSInfo m_struGPSInfo;
|
||||||
//FodisRP m_struMiscRunParams;
|
//FodisRP m_struMiscRunParams;
|
||||||
@ -37,9 +36,18 @@ int main(int argc, char* argv[])
|
|||||||
DataFileProcessor m_dfpDataSaver;
|
DataFileProcessor m_dfpDataSaver;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////test code block
|
||||||
|
//DataFrame aaaa;
|
||||||
|
//int xxxx = sizeof(aaaa);
|
||||||
|
//m_dfpDataSaver.LoadWaveLengthFile("E:/WavelengthInfo.txt");
|
||||||
|
//m_dfpDataSaver.LoadSingleDataFile("D:/15_55_18.datrecv");
|
||||||
|
//m_dfpDataSaver.RecoverBackground("D:/15_55_18.dat", "D:/DCTable.txt");
|
||||||
|
//////////////////////////////////////////////////////////////////////////test code block
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////Check Settings File
|
//////////////////////////////////////////////////////////////////////////Check Settings File
|
||||||
|
bool bRes = false;
|
||||||
|
|
||||||
QFileInfo m_qfiSettingFileInfo("/home/data/Setting/DeviceSettings.ini");
|
QFileInfo m_qfiSettingFileInfo("/home/data/Setting/DeviceSettings.ini");
|
||||||
QFileInfo m_qfiDCTFileInfo("/home/data/Data/DCTable.txt");
|
|
||||||
|
|
||||||
if (!m_qfiSettingFileInfo.isFile())
|
if (!m_qfiSettingFileInfo.isFile())
|
||||||
{
|
{
|
||||||
@ -63,40 +71,10 @@ int main(int argc, char* argv[])
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////////Check Settings File
|
||||||
if (!m_qfiDCTFileInfo.isFile())
|
|
||||||
{
|
|
||||||
printf ("DCTable File Missing !!! Will create from default one.");
|
|
||||||
|
|
||||||
QDir qdirPath("/home/data/Data");
|
|
||||||
if (!qdirPath.exists())
|
|
||||||
{
|
|
||||||
bool bRes = qdirPath.mkpath("/home/data/Data");
|
|
||||||
if (!bRes)
|
|
||||||
{
|
|
||||||
qDebug() << "DataFileProcessor mkdir Failed.";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool bRes = QFile::copy("/root/DCTable.txt", "/home/data/Data/DCTable.txt");
|
//////////////////////////////////////////////////////////////////////////Load Settings File
|
||||||
if (!bRes)
|
|
||||||
{
|
|
||||||
qDebug() << " QFile::copy Failed.";
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///test
|
|
||||||
//m_dfpDataSaver.LoadWaveLengthFile("E:/WavelengthInfo.txt");
|
|
||||||
//m_dfpDataSaver.LoadSingleDataFile("E:/11_06_45.dat");
|
|
||||||
|
|
||||||
///configger
|
///configger
|
||||||
m_syscfSettings.Initialize();
|
m_syscfSettings.Initialize();
|
||||||
bRes = m_syscfSettings.LoadSettings_FS(m_struFSParam);
|
bRes = m_syscfSettings.LoadSettings_FS(m_struFSParam);
|
||||||
@ -114,14 +92,52 @@ int main(int argc, char* argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/////
|
/////
|
||||||
//test only
|
//////////////////////////////////////////////////////////////////////////Check DCTable
|
||||||
|
using namespace ZZ_MISCDEF;
|
||||||
|
if (m_struFSParam.ucDeviceModel== DeviceModel::FLAME)
|
||||||
|
{
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QFileInfo m_qfiDCTFileInfo("/home/data/Data/DCTable.txt");
|
||||||
|
if (!m_qfiDCTFileInfo.isFile())
|
||||||
|
{
|
||||||
|
printf("DCTable File Missing !!! Will create from default one.");
|
||||||
|
|
||||||
//MakeDCT m_test;
|
QDir qdirPath("/home/data/Data");
|
||||||
// m_test.SetRunParams(m_struFSParam);
|
if (!qdirPath.exists())
|
||||||
// m_test.Initialize();
|
{
|
||||||
// m_test.MakeTable();
|
bool bRes = qdirPath.mkpath("/home/data/Data");
|
||||||
//m_test.Initialize_Part();
|
if (!bRes)
|
||||||
//m_test.LoadTable();
|
{
|
||||||
|
qDebug() << "DataFileProcessor mkdir Failed.";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool bRes = QFile::copy("/root/DCTable.txt", "/home/data/Data/DCTable.txt");
|
||||||
|
if (!bRes)
|
||||||
|
{
|
||||||
|
qDebug() << " QFile::copy Failed.";
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////////Check DCTable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////test only
|
||||||
|
//MakeDCT m_test;
|
||||||
|
//m_test.SetRunParams(m_struFSParam);
|
||||||
|
//m_test.Initialize();
|
||||||
|
//m_test.MakeTable();
|
||||||
|
//m_test.Initialize_Part();
|
||||||
|
//m_test.LoadTable();
|
||||||
|
////////////////////////////////test only
|
||||||
|
|
||||||
m_ctrlGPS.SetContext(m_mgMainGrabber);//<2F><>ʼ<EFBFBD><CABC>gps
|
m_ctrlGPS.SetContext(m_mgMainGrabber);//<2F><>ʼ<EFBFBD><CABC>gps
|
||||||
m_ctrlGPS.SetupMessagePipeline();
|
m_ctrlGPS.SetupMessagePipeline();
|
||||||
@ -138,7 +154,7 @@ int main(int argc, char* argv[])
|
|||||||
m_mgMainGrabber.Initialize();//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
m_mgMainGrabber.Initialize();//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
||||||
|
|
||||||
//m_ctrlGPS.SyncDateOnce();
|
//m_ctrlGPS.SyncDateOnce();
|
||||||
cout << "Hello CMake." << endl;
|
cout << "System Started..." << endl;
|
||||||
///////
|
///////
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user