WLG/uart/uart_feature_parse.cpp
2024-10-22 20:56:21 +08:00

1296 lines
60 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.

#include "uart.hpp"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
std::vector<RecvData> g_VecWaveDataX;
std::vector<RecvData> g_VecWaveDataY;
std::vector<RecvData> g_VecWaveDataZ;
map<std::string, compressWaveChannel> g_mapCompress;
void Uart::RecordBattery(std::string &strLongAddr, DataRecvStatic &dataStatic, std::string &nowTimetamp) {
char insertSql[1024] = {0};
sprintf(insertSql, "'%s','%d','%f','%f','%f','%d','','','%s'", strLongAddr.c_str(), dataStatic.Dip, dataStatic.TemBot, dataStatic.nodeWorkTime, dataStatic.nodeSendTime, dataStatic.Voltage, nowTimetamp.c_str());
sqlite_db_ctrl::instance().InsertData(T_BATTERY_INFO(TNAME), insertSql);
}
void Uart::DealDataNodeFeature(const char *pData, int flag) {
print_info("recv feature\n");
RecvData *pRecvData = (RecvData *)pData;
char whereCon[1024] = {0};
char updateSql[1024] = {0};
char buf[20] = {0x00};
int nodeResend = 0, timing = 0;
sprintf(buf, "%02x%02x", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]);
if (flag == 1) {
LOG_INFO("DealDataNodeFeature %02x%02x, %d\n", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1], flag);
}
if (bSendTimeStamp) //波形处理中
return;
std::string strShortAddr = std::string(buf);
print_info("zigbeeShortAddr='%s'\n", strShortAddr.c_str());
char getLongAddr_sql[32] = {0};
//根据数据包中的传感器的短地址获取数据库中长地址MAC在下面判断该传感器是否存在如果不存在则把数据包丢弃
sprintf(getLongAddr_sql, "zigbeeShortAddr='%s'", strShortAddr.c_str());
vec_t vecResult = sqlite_db_ctrl::instance().GetDataSingleLine(T_SENSOR_INFO(TNAME), " softVersion,dataNodeNo,MeasurementID,ProductNo ", getLongAddr_sql);
if (vecResult.size() < 1) {
LOG_ERROR("device info not found %02x%02x\n", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]);
print_error("device info not found\n");
return;
}
print_info("--------->the remote sensor short addr:%s strLongAddr=%s,softVersion = %s\n", buf, vecResult[1].c_str(), vecResult[0].c_str());
std::string strLongAddr = vecResult[1];
std::string strMeasurementID = vecResult[2];
std::string strProductNo = vecResult[3];
if (1 == flag) {
tcflush(fd, TCIOFLUSH);
if (!bSendTimeStamp) {
bSendTimeStamp = true;
modify_distaddr_info(0x9999, "", pRecvData->ShortAddr); //临时参数配置
mssleep(10000);
LOG_DEBUG("Zigbee Signal !\n");
int Times = 0;
mssleep(20000);
while (Times < 3) {
getZigbeeSignal(pRecvData->ShortAddr);
Times++;
mssleep(20000);
}
mssleep(10000);
timing = UpdateWirelessNodeTime((unsigned char *)pRecvData->ShortAddr, 0);
} else {
return;
}
GlobalConfig::ZigbeeInfo_G.MyAddr = "9999";
GlobalConfig::Zigbee_G.MyAddr = 0x9999;
string strTime = GetLocalTimeWithMs();
m_strDestShortAddr = std::string(buf);
bool isUpdate = ReadUpdatePackge(pRecvData->ShortAddr);
bUpdatePre = isUpdate;
if (!isUpdate) {
int iRet = UpdateConfig(pRecvData->ShortAddr);
}
if (isUpdate || bUpdateconfig) {
} else {
LOG_DEBUG("DealDataNodeFeature %02x%02x,localaddr %02x%02x \n", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1], UINT16_HIGH(GlobalConfig::Zigbee_G.MyAddr), UINT16_LOW(GlobalConfig::Zigbee_G.MyAddr));
// 进入传输原始数据状态,启动计数 60秒
GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = ENTER_TRANSMITTING_STATUS;
GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0;
}
unsigned char compressChannel = pRecvData->Data[34];
compressWaveChannel tempchannel;
tempchannel.compressChannelX = GET_BIT(compressChannel, 0);
tempchannel.compressChannelY = GET_BIT(compressChannel, 2);
tempchannel.compressChannelZ = GET_BIT(compressChannel, 4);
if (strProductNo == "01") {
tempchannel.CountX = BUILD_UINT16(pRecvData->Data[55], pRecvData->Data[54]);
tempchannel.CountY = BUILD_UINT16(pRecvData->Data[57], pRecvData->Data[56]);
tempchannel.CountZ = BUILD_UINT16(pRecvData->Data[59], pRecvData->Data[58]);
} else if (strProductNo == "02") {
int CountX = 0;
int CountY = 0;
int CountZ = 0;
unsigned char buffer[6] = {0x00};
memcpy(buffer, &pRecvData->Data[55], 1);
memcpy(buffer + 1, &pRecvData->Data[54], 1);
memcpy(buffer + 2, &pRecvData->Data[57], 1);
memcpy(buffer + 3, &pRecvData->Data[56], 1);
memcpy(buffer + 4, &pRecvData->Data[59], 1);
memcpy(buffer + 5, &pRecvData->Data[58], 1);
uint64_t packed_data = 0;
for (int i = 0; i < 6; i++) {
packed_data |= (uint64_t)buffer[i] << (8 * (5 - i)); // 从高位开始组合
}
// 输出结果
printf("Resulting 48-bit integer: 0x%012llX\n", packed_data);
// 提取 15 位的第一个数据
tempchannel.CountX = (packed_data >> 33) & 0x7FFF; // 提取最高的 15 位
// 提取 15 位的第二个数据
tempchannel.CountY = (packed_data >> 18) & 0x7FFF; // 提取中间的 15 位
// 提取 18 位的第三个数据
tempchannel.CountZ = packed_data & 0x3FFFF; // 提取最低的 18 位
}
g_mapCompress[strShortAddr] = tempchannel;
print_info("count X = %d,Y = %d,Z = %d\n", tempchannel.CountX, tempchannel.CountY, tempchannel.CountZ);
print_info("compress X = %d,Y = %d,Z = %d \n", tempchannel.compressChannelX, tempchannel.compressChannelY, tempchannel.compressChannelZ);
} else {
memset(whereCon, 0x00, sizeof(whereCon));
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(whereCon, "zigbeeShortAddr='%s'", strShortAddr.c_str());
sprintf(updateSql, " StaticTime = StaticTime + 1");
sqlite_db_ctrl::instance().UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon);
}
if (vecResult[0] == "3.0" || vecResult[0] == "4.0") {
return;
}
long staticIndex = BUILD_UINT32(pRecvData->Data[29], pRecvData->Data[28], pRecvData->Data[27], pRecvData->Data[26]);
print_info("staticIndex = %d\n", staticIndex);
// LOG_INFO("staticIndex = %d\n",staticIndex);
char localtimestamp[32] = {0};
GetTimeNet(localtimestamp, 1);
std::string nowTimetamp = std::string(localtimestamp);
strTimetamp = nowTimetamp;
int iTemp = 0;
unsigned char highbit = 0;
unsigned int lowbit = 0;
float n = 0;
DataRecvStatic dataStatic;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[5], pRecvData->Data[4]);
print_blue("!!!!!!!!!!!!!!!!!!!!!!%s\n", buf);
iTemp = (int)strtol(buf, NULL, 16);
dataStatic.Dip = iTemp;
int fTemp = 0;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[1], pRecvData->Data[0]);
print_blue("@@@@@@@@@@@@@@@@@%s\n", buf);
iTemp = (int)strtol(buf, NULL, 16);
if (iTemp < 0x8000) {
fTemp = iTemp;
} else {
fTemp = (((~iTemp) & 0xffff) + 1) * (-1);
}
dataStatic.TemBot = fTemp * 0.0625; //设备温度
fTemp = 0;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[3], pRecvData->Data[2]);
iTemp = (int)strtol(buf, NULL, 16);
if (iTemp < 0x8000) {
fTemp = iTemp;
} else {
fTemp = (((~iTemp) & 0xffff) + 1) * (-1);
}
dataStatic.TemTop = fTemp * 0.0625; //环境温度
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[7], pRecvData->Data[6]);
iTemp = (int)strtol(buf, NULL, 16);
dataStatic.Voltage = iTemp;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[31], pRecvData->Data[30]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataStatic.nodeWorkTime = lowbit * n;
print_info("workTime = %f\n", dataStatic.nodeWorkTime);
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[33], pRecvData->Data[32]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataStatic.nodeSendTime = lowbit * n;
print_info("SendTime = %f\n", dataStatic.nodeSendTime);
dataStatic.nodeWorkTime = dataStatic.nodeWorkTime - dataStatic.nodeSendTime;
RecordBattery(strLongAddr, dataStatic, nowTimetamp);
char szTableName[50] = {0x00}, szTableNameStatic[50] = {0x00}, szTableNameData[50] = {0x00};
sprintf(szTableName, "t_dataStatic_%s", strLongAddr.c_str());
memcpy(szTableNameStatic, szTableName, sizeof(szTableNameStatic));
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "StaticIndex = %d", staticIndex);
int count = sqlite_db_ctrl::instance().GetTableRows(szTableNameStatic, whereCon); //避免重复数据
sprintf(szTableNameData, "t_data_%s", strLongAddr.c_str());
int count2 = sqlite_db_ctrl::instance().GetTableRows(szTableNameData, whereCon);
if (count > 0 || count2 > 0) {
char logInfo[20] = {0x00};
sprintf(logInfo, "ShortAddr = %s,staticIndex = %d,staticData = %d, data = %d", strShortAddr.c_str(), staticIndex, count, count2);
LOG_DEBUG(logInfo);
return;
}
memset(whereCon, 0x00, sizeof(whereCon));
///////////////////////////////////////////////////////////// for V2.0.3 upgrade to V3.0
std::string strTmp = "";
char sztmp[100] = {0x00};
strTmp = "name = '" + std::string(szTableNameStatic) + "' and sql LIKE '%nodeResend%' ";
int row = sqlite_db_ctrl::instance().GetTableRows(" sqlite_master ", strTmp.c_str());
print_info("row1 = %d\n", row);
if (row == 0) {
memset(sztmp, 0x00, sizeof(sztmp));
sprintf(sztmp, "ALTER TABLE %s ADD COLUMN 'nodeResend'", szTableNameStatic);
sqlite_db_ctrl::instance().CreateTable(sztmp);
}
strTmp = "name = '" + std::string(szTableNameData) + "' and sql LIKE '%nodeResend%' ";
row = sqlite_db_ctrl::instance().GetTableRows(" sqlite_master ", strTmp.c_str());
print_info("row2 = %d\n", row);
if (row == 0) {
memset(sztmp, 0x00, sizeof(sztmp));
sprintf(sztmp, "ALTER TABLE %s ADD COLUMN 'nodeResend'", szTableNameData);
sqlite_db_ctrl::instance().CreateTable(sztmp);
}
////////////////////////////////////////////////////////////更换电池判断
sprintf(whereCon, " dataNodeNo = '%s' and StaticIndex > 0 order by StaticIndex desc LIMIT 0 , 1 ", strLongAddr.c_str());
std::string strStaticIndex = sqlite_db_ctrl::instance().GetData(szTableNameStatic, "StaticIndex", whereCon);
if (atol(strStaticIndex.c_str()) - staticIndex > 100) {
sqlite_db_ctrl::instance().Deletetable(szTableNameStatic);
sqlite_db_ctrl::instance().Deletetable(szTableNameData);
LOG_INFO("staticIndexNOW = %d,strStaticIndexLast = %s\n", staticIndex, strStaticIndex.c_str());
}
print_info("NowstaticIndex = %d,RecordStaticIndex = %d", staticIndex, atol(strStaticIndex.c_str()));
if (staticIndex != atol(strStaticIndex.c_str() + 1) && strStaticIndex != "" && staticIndex < atol(strStaticIndex.c_str())) {
sprintf(whereCon, "StaticIndex = %d order by StaticIndex desc LIMIT 0 , 1", atol(strStaticIndex.c_str()));
vec_t vecResult = sqlite_db_ctrl::instance().GetDataSingleLine(szTableNameStatic, "timeStamp,StaticIndex", whereCon);
if (vecResult.size() > 0) {
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "dataNodeNo = '%s'", strLongAddr.c_str());
string staticInterval = sqlite_db_ctrl::instance().GetData(T_SENSOR_INFO(TNAME), "featureInterval", whereCon);
long nNowTimetamp = atol(vecResult[0].c_str()) - (atol(staticInterval.c_str()) * (atol(vecResult[1].c_str()) - staticIndex)) * 60;
char tmp[10] = {0x00};
sprintf(tmp, "%ld", nNowTimetamp);
nowTimetamp = std::string(tmp);
nodeResend = 1;
}
}
print_info("nowTimetamp = %s", nowTimetamp.c_str());
// save dataStatic of 7 days
char selectCon[128] = {0};
sprintf(selectCon, "channelID='%s' ORDER BY timeStamp ASC LIMIT 0,1", (strMeasurementID + "-S").c_str());
std::string strTime = sqlite_db_ctrl::instance().GetData(szTableName, "timeStamp", selectCon);
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-S").c_str());
int Count = sqlite_db_ctrl::instance().GetTableRows(szTableName, whereCon);
if (Count == -1) {
sqlite_db_ctrl::instance().CreatedataStatictable(szTableName);
}
print_info("strLongAddr = %s,strTime = %s\n", strLongAddr.c_str(), strTime.c_str());
long lTime = atol(nowTimetamp.c_str()) - atol(strTime.c_str());
print_info("lTime = %d,OneWeek = %d\n", lTime, OneWeek);
print_info("dataStatic.TemTop : %f dataStatic.TemBot : %f dataStatic.Dip :%d dataStatic.Voltage : %d\n", dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage);
sprintf(updateSql, "temTop='%f',temBot='%f',dip='%d',voltage='%d',timeStamp='%s',StaticIndex = %d, nodeResend = %d,zigbeeSignal = '',zigbeeSignalNode = '',statisticType = '%d',timing = '%d' ", dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage,
nowTimetamp.c_str(), staticIndex, nodeResend, flag, timing);
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-S").c_str());
if (/*0 == sqlite_db_ctrl::instance().GetTableRows(T_DATASTATIC_INFO(TNAME), whereCon)*/ (Count * 3 < SAVE_COUNT && lTime < OneWeek) || strTime.size() == 0) {
print_info("insert static data to sql\n");
char insertSql[1024] = {0};
sprintf(insertSql, "'%s','%s','%f','%f','%d','%d','',%d,'%s','1',%d,'','%d','%d'", strLongAddr.c_str(), (strMeasurementID + "-S").c_str(), dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, staticIndex, nowTimetamp.c_str(), nodeResend, flag,
timing);
sqlite_db_ctrl::instance().InsertData(szTableName, insertSql);
if (0 == sqlite_db_ctrl::instance().GetTableRows(T_DATASTATIC_INFO(TNAME), whereCon)) { // First Connect
char insertSql[1024] = {0};
sprintf(insertSql, "'%s','%s','%f','%f','%d','%d','',%d,'%s','1',%d", strLongAddr.c_str(), (strMeasurementID + "-S").c_str(), dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, staticIndex, nowTimetamp.c_str(), nodeResend);
sqlite_db_ctrl::instance().InsertData(T_DATASTATIC_INFO(TNAME), insertSql);
sqlite_db_ctrl::instance().CalculateBattery();
} else {
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(updateSql, "temTop='%f',temBot='%f',dip='%d',voltage='%d',timeStamp='%s',StaticIndex = %d ", dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, nowTimetamp.c_str(), staticIndex);
sqlite_db_ctrl::instance().UpdateTableData(T_DATASTATIC_INFO(TNAME), updateSql, whereCon);
}
} else {
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s'", (strMeasurementID + "-S").c_str(), strTime.c_str());
print_info("update static data to sql\n");
sqlite_db_ctrl::instance().UpdateTableData(szTableName, updateSql, whereCon);
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-S").c_str());
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(updateSql, "temTop='%f',temBot='%f',dip='%d',voltage='%d',timeStamp='%s',StaticIndex = %d ", dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, nowTimetamp.c_str(), staticIndex);
sqlite_db_ctrl::instance().UpdateTableData(T_DATASTATIC_INFO(TNAME), updateSql, whereCon);
}
memset(szTableName, 0x00, sizeof(szTableName));
sprintf(szTableName, "t_data_%s", strLongAddr.c_str());
if (Count == -1) {
sqlite_db_ctrl::instance().Createtable(szTableName);
}
DataRecvDym dataDymX;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[9], pRecvData->Data[8]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.DiagnosisPk = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[11], pRecvData->Data[10]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.RmsValues = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[13], pRecvData->Data[12]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.IntegratPk = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[15], pRecvData->Data[14]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.IntegratRMS = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[17], pRecvData->Data[16]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.Amp1 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[19], pRecvData->Data[18]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.Amp2 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[21], pRecvData->Data[20]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.Amp3 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[23], pRecvData->Data[22]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.Amp4 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[25], pRecvData->Data[24]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymX.Amp5 = lowbit * n;
memset(buf, 0, sizeof(buf));
dataDymX.EnvelopEnergy = 0;
memset(buf, 0, sizeof(buf));
dataDymX.Phase1 = 0;
memset(buf, 0, sizeof(buf));
dataDymX.Phase2 = 0;
memset(buf, 0, sizeof(buf));
memset(buf, 0, 8);
dataDymX.Phase3 = 0;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[35], pRecvData->Data[34]);
dataDymX.Phase4 = 0;
memset(whereCon, 0, 1024);
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-X").c_str());
memset(updateSql, 0, 1024);
sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\
Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s',StaticIndex = %d,nodeResend = %d ",
dataDymX.DiagnosisPk, dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues, dataDymX.EnvelopEnergy, dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5, dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4,
nowTimetamp.c_str(), staticIndex, nodeResend);
if ((Count * 3 < SAVE_COUNT && lTime < OneWeek) || strTime.size() == 0) { // 1 week
char insertSql[1024] = {0};
memset(insertSql, 0x00, sizeof(insertSql));
sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f',%d,'%s','1',%d", strLongAddr.c_str(), (strMeasurementID + "-X").c_str(), dataDymX.DiagnosisPk, dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues,
dataDymX.EnvelopEnergy, dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5, dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, staticIndex, nowTimetamp.c_str(), nodeResend);
sqlite_db_ctrl::instance().InsertData(szTableName, insertSql);
if (0 == sqlite_db_ctrl::instance().GetTableRows(T_DATA_INFO(TNAME), whereCon))
sqlite_db_ctrl::instance().InsertData(T_DATA_INFO(TNAME), insertSql);
else
sqlite_db_ctrl::instance().UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon);
} else {
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s'", (strMeasurementID + "-X").c_str(), strTime.c_str());
sqlite_db_ctrl::instance().UpdateTableData(szTableName, updateSql, whereCon);
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-X").c_str());
sqlite_db_ctrl::instance().UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon);
}
print_info("x:%s,%s,diagnosisPk=%f,integratPk=%f,integratRMS=%f,rmsValues=%f,envelopEnergy=%f,Amp1=%f,Amp2=%f,Amp3=%f,Amp4=%f,Amp5=%f,Phase1=%f,Phase2=%f,Phase3=%f,Phase4=%f,timeStamp=%s\n", strLongAddr.c_str(), (strMeasurementID + "-X").c_str(), dataDymX.DiagnosisPk,
dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues, dataDymX.EnvelopEnergy, dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5, dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, nowTimetamp.c_str());
Json::Value valNodeData;
Json::Value valNodeFeature;
valNodeFeature["dataNodeNo"] = strMeasurementID;
valNodeFeature["ChannelId"] = strMeasurementID + "-X";
valNodeFeature["diagnosisPk"] = dataDymX.DiagnosisPk;
valNodeFeature["integratPk"] = dataDymX.IntegratPk;
valNodeFeature["integratRMS"] = dataDymX.IntegratRMS;
valNodeFeature["rmsValues"] = dataDymX.RmsValues;
valNodeFeature["envelopEnergy"] = dataDymX.EnvelopEnergy;
valNodeFeature["Amp1"] = dataDymX.Amp1;
valNodeFeature["Amp2"] = dataDymX.Amp2;
valNodeFeature["Amp3"] = dataDymX.Amp3;
valNodeFeature["Amp4"] = dataDymX.Amp4;
valNodeFeature["Amp5"] = dataDymX.Amp5;
valNodeFeature["Phase1"] = dataDymX.Phase1;
valNodeFeature["Phase2"] = dataDymX.Phase2;
valNodeFeature["Phase3"] = dataDymX.Phase3;
valNodeFeature["Phase4"] = dataDymX.Phase4;
valNodeFeature["timeStamp"] = nowTimetamp;
valNodeData.append(valNodeFeature);
DataRecvDym dataDymY;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[37], pRecvData->Data[36]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.DiagnosisPk = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[39], pRecvData->Data[38]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.RmsValues = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[41], pRecvData->Data[40]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.IntegratPk = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[43], pRecvData->Data[42]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.IntegratRMS = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[45], pRecvData->Data[44]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.Amp1 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[47], pRecvData->Data[46]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.Amp2 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[49], pRecvData->Data[48]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.Amp3 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[51], pRecvData->Data[50]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.Amp4 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[53], pRecvData->Data[52]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymY.Amp5 = lowbit * n;
memset(buf, 0, sizeof(buf));
dataDymY.EnvelopEnergy = 0;
memset(buf, 0, sizeof(buf));
dataDymY.Phase1 = 0;
memset(buf, 0, sizeof(buf));
dataDymY.Phase2 = 0;
memset(buf, 0, sizeof(buf));
dataDymY.Phase3 = 0;
memset(buf, 0, sizeof(buf));
dataDymY.Phase4 = 0;
memset(whereCon, 0, 1024);
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-Y").c_str());
memset(updateSql, 0, 1024);
sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\
Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s',StaticIndex = %d,nodeResend = %d ",
dataDymY.DiagnosisPk, dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues, dataDymY.EnvelopEnergy, dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5, dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4,
nowTimetamp.c_str(), staticIndex, nodeResend);
if (/*0 == sqlite_db_ctrl::instance().GetTableRows(T_DATA_INFO(TNAME), whereCon)*/ (Count * 3 < SAVE_COUNT && lTime < OneWeek) || strTime.size() == 0) {
char insertSql[1024] = {0};
memset(insertSql, 0x00, sizeof(insertSql));
sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f',%d,'%s','1',%d", strLongAddr.c_str(), (strMeasurementID + "-Y").c_str(), dataDymY.DiagnosisPk, dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues,
dataDymY.EnvelopEnergy, dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5, dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4, staticIndex, nowTimetamp.c_str(), nodeResend);
sqlite_db_ctrl::instance().InsertData(szTableName, insertSql);
if (0 == sqlite_db_ctrl::instance().GetTableRows(T_DATA_INFO(TNAME), whereCon))
sqlite_db_ctrl::instance().InsertData(T_DATA_INFO(TNAME), insertSql);
else
sqlite_db_ctrl::instance().UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon);
} else {
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s'", (strMeasurementID + "-Y").c_str(), strTime.c_str());
sqlite_db_ctrl::instance().UpdateTableData(szTableName, updateSql, whereCon);
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-Y").c_str());
sqlite_db_ctrl::instance().UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon);
}
print_info("y: %s,%s,diagnosisPk=%f,integratPk=%f,integratRMS=%f,rmsValues=%f,envelopEnergy=%f,Amp1=%f,Amp2=%f,Amp3=%f,Amp4=%f,Amp5=%f,Phase1=%f,Phase2=%f,Phase3=%f,Phase4=%f,timeStamp=%s\n", strLongAddr.c_str(), (strMeasurementID + "-Y").c_str(), dataDymY.DiagnosisPk,
dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues, dataDymY.EnvelopEnergy, dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5, dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4, nowTimetamp.c_str());
valNodeFeature["dataNodeNo"] = strMeasurementID;
valNodeFeature["ChannelId"] = strMeasurementID + "-Y";
valNodeFeature["diagnosisPk"] = dataDymY.DiagnosisPk;
valNodeFeature["integratPk"] = dataDymY.IntegratPk;
valNodeFeature["integratRMS"] = dataDymY.IntegratRMS;
valNodeFeature["rmsValues"] = dataDymY.RmsValues;
valNodeFeature["envelopEnergy"] = dataDymY.EnvelopEnergy;
valNodeFeature["Amp1"] = dataDymY.Amp1;
valNodeFeature["Amp2"] = dataDymY.Amp2;
valNodeFeature["Amp3"] = dataDymY.Amp3;
valNodeFeature["Amp4"] = dataDymY.Amp4;
valNodeFeature["Amp5"] = dataDymY.Amp5;
valNodeFeature["Phase1"] = dataDymY.Phase1;
valNodeFeature["Phase2"] = dataDymY.Phase2;
valNodeFeature["Phase3"] = dataDymY.Phase3;
valNodeFeature["Phase4"] = dataDymY.Phase4;
valNodeFeature["timeStamp"] = nowTimetamp;
valNodeData.append(valNodeFeature);
DataRecvDym dataDymZ;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[65], pRecvData->Data[64]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.DiagnosisPk = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[67], pRecvData->Data[66]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.RmsValues = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[69], pRecvData->Data[68]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.IntegratPk = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[71], pRecvData->Data[70]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.IntegratRMS = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[73], pRecvData->Data[72]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Amp1 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[75], pRecvData->Data[74]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Amp2 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[77], pRecvData->Data[76]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Amp3 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[79], pRecvData->Data[78]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Amp4 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[81], pRecvData->Data[80]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Amp5 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[83], pRecvData->Data[82]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.EnvelopEnergy = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[85], pRecvData->Data[84]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Phase1 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[87], pRecvData->Data[86]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Phase2 = lowbit * n;
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02x%02x", pRecvData->Data[89], pRecvData->Data[88]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Phase3 = lowbit * n;
sprintf(buf, "%02x%02x", pRecvData->Data[91], pRecvData->Data[90]);
iTemp = (unsigned int)strtol(buf, NULL, 16);
highbit = iTemp >> 14 & 0x3;
lowbit = iTemp & 0x3fff;
n = ScaleConvert(highbit);
dataDymZ.Phase4 = lowbit * n;
memset(whereCon, 0, 1024);
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-Z").c_str());
memset(updateSql, 0, 1024);
sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\
Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s',StaticIndex = %d,nodeResend = %d ",
dataDymZ.DiagnosisPk, dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues, dataDymZ.EnvelopEnergy, dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5, dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4,
nowTimetamp.c_str(), staticIndex, nodeResend);
if (/*0 == sqlite_db_ctrl::instance().GetTableRows(T_DATA_INFO(TNAME), whereCon)*/ Count * 3 < SAVE_COUNT && (lTime < OneWeek || strTime.size() == 0)) {
char insertSql[1024] = {0};
memset(insertSql, 0x00, sizeof(insertSql));
sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f',%d,'%s','1',%d", strLongAddr.c_str(), (strMeasurementID + "-Z").c_str(), dataDymZ.DiagnosisPk, dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues,
dataDymZ.EnvelopEnergy, dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5, dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, staticIndex, nowTimetamp.c_str(), nodeResend);
sqlite_db_ctrl::instance().InsertData(szTableName, insertSql);
if (0 == sqlite_db_ctrl::instance().GetTableRows(T_DATA_INFO(TNAME), whereCon))
sqlite_db_ctrl::instance().InsertData(T_DATA_INFO(TNAME), insertSql);
else
sqlite_db_ctrl::instance().UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon);
} else {
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s'", (strMeasurementID + "-Z").c_str(), strTime.c_str());
sqlite_db_ctrl::instance().UpdateTableData(szTableName, updateSql, whereCon);
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' ", (strMeasurementID + "-Z").c_str());
sqlite_db_ctrl::instance().UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon);
}
print_info("Z: %s,%s,diagnosisPk=%f,integratPk=%f,integratRMS=%f,rmsValues=%f,envelopEnergy=%f,Amp1=%f,Amp2=%f,Amp3=%f,Amp4=%f,Amp5=%f,Phase1=%f,Phase2=%f,Phase3=%f,Phase4=%f,timeStamp=%s\n", strLongAddr.c_str(), (strMeasurementID + "-Z").c_str(), dataDymZ.DiagnosisPk,
dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues, dataDymZ.EnvelopEnergy, dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5, dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, nowTimetamp.c_str());
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "dataNodeNo='%s'", strLongAddr.c_str());
sqlite_db_ctrl::instance().UpdateTableData(T_SENSOR_INFO(TNAME), "status='1'", whereCon);
//无线传感器Z信息
valNodeFeature["dataNodeNo"] = strMeasurementID;
valNodeFeature["ChannelId"] = strMeasurementID + "-Z";
valNodeFeature["diagnosisPk"] = dataDymZ.DiagnosisPk;
valNodeFeature["integratPk"] = dataDymZ.IntegratPk;
valNodeFeature["integratRMS"] = dataDymZ.IntegratRMS;
valNodeFeature["rmsValues"] = dataDymZ.RmsValues;
valNodeFeature["envelopEnergy"] = dataDymZ.EnvelopEnergy;
valNodeFeature["Amp1"] = dataDymZ.Amp1;
valNodeFeature["Amp2"] = dataDymZ.Amp2;
valNodeFeature["Amp3"] = dataDymZ.Amp3;
valNodeFeature["Amp4"] = dataDymZ.Amp4;
valNodeFeature["Amp5"] = dataDymZ.Amp5;
valNodeFeature["Phase1"] = dataDymZ.Phase1;
valNodeFeature["Phase2"] = dataDymZ.Phase2;
valNodeFeature["Phase3"] = dataDymZ.Phase3;
valNodeFeature["Phase4"] = dataDymZ.Phase4;
valNodeFeature["timeStamp"] = nowTimetamp;
valNodeData.append(valNodeFeature);
memset(whereCon, 0, 1024);
sprintf(whereCon, "dataNodeNo='%s'", strLongAddr.c_str());
std::string strBattery = sqlite_db_ctrl::instance().GetData(T_SENSOR_INFO(TNAME), "batteryPower", whereCon);
vector<std::string> vBattery;
vBattery.push_back("0");
vBattery.push_back("0");
if (strBattery.length() > 0) {
boost::split(vBattery, strBattery, boost::is_any_of(","), boost::token_compress_on);
}
//无线传感器信息
Json::Value root;
Json::Value valdatastatic;
valdatastatic["TemperatureTop"] = dataStatic.TemTop;
valdatastatic["TemperatureBot"] = dataStatic.TemBot;
valdatastatic["WorkTime"] = dataStatic.nodeWorkTime;
valdatastatic["SendTime"] = dataStatic.nodeSendTime;
valdatastatic["Dip"] = dataStatic.Dip;
valdatastatic["Voltage"] = dataStatic.Voltage;
valdatastatic["ChannelType"] = "STATUS";
valdatastatic["ChannelId"] = strMeasurementID + "-S";
valdatastatic["TimeStamp"] = nowTimetamp;
valdatastatic["bateryProportion"] = atof(vBattery[1].c_str()) / atof(vBattery[0].c_str());
valdatastatic["batteryRemainDay"] = atof(vBattery[1].c_str());
valdatastatic["dataNodeNo"] = strMeasurementID;
valNodeData.append(valdatastatic);
root["data"] = valNodeData;
root["TimeStamp"] = nowTimetamp;
root["dataNodeNo"] = strMeasurementID;
root["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G;
Json::FastWriter featureValue;
std::string strstatisticData = featureValue.write(root);
//传感器发来的数据包中的表示设备信息的数据转化为json格式后通过调用data_publish将数据传给mqttclient Topicwireless/cmd/60294D203717
int iRet = data_publish(strstatisticData.c_str(), GlobalConfig::Topic_G.mPubData.c_str());
print_info("dataNodeNo = '%s' and TimeStamp = '%s',MQTT ret = %d\n", strLongAddr.c_str(), nowTimetamp.c_str(), iRet);
if (iRet != 0) {
char updateSql[1024] = {0};
memset(whereCon, 0, 64);
sprintf(whereCon, "dataNodeNo = '%s' and TimeStamp = '%s'", strLongAddr.c_str(), nowTimetamp.c_str());
memcpy(updateSql, "sendMsg='0'", sizeof(updateSql));
sqlite_db_ctrl::instance().UpdateTableData(szTableNameStatic, updateSql, whereCon);
sqlite_db_ctrl::instance().UpdateTableData(szTableNameData, updateSql, whereCon);
}
//综上代码把静态数据x y z轴的特征值存放到sql数据库中如果数据原来不存在则插入新数据如果存在则更新数据
print_info("Dip : %d TemBot : %f TemBot : %f Voltage : %d\n", dataStatic.Dip, dataStatic.TemBot, dataStatic.TemTop, dataStatic.Voltage);
memset(selectCon, 0x00, sizeof(selectCon));
sprintf(selectCon, "zigbeeSignal <> '' ORDER BY timeStamp desc LIMIT 0,1");
strTime = sqlite_db_ctrl::instance().GetData(szTableNameStatic, "timeStamp", selectCon);
if (flag == 1) {
LOG_INFO("DealDataNodeFeature end %02x%02x\n", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]);
}
}
float Uart::ScaleConvert(int highbit) { return 0.0001f * pow(100.0f, highbit); }
void Uart::DealDataNodeWave(const char *pData, int comand) {
RecvData *pRecvData = (RecvData *)pData;
if (wave_trans_) {
if (comand == 3) {
VecWaveDataX.push_back(*pRecvData);
} else if (comand == 4) {
VecWaveDataY.push_back(*pRecvData);
} else if (comand == 5) {
VecWaveDataZ.push_back(*pRecvData);
}
} else {
if (comand == 3) {
g_VecWaveDataX[m_waveCountX] = *pRecvData;
m_waveCountX++;
} else if (comand == 4) {
g_VecWaveDataY[m_waveCountY] = *pRecvData;
m_waveCountY++;
} else if (comand == 5) {
g_VecWaveDataZ[m_waveCountZ] = *pRecvData;
m_waveCountZ++;
}
}
char localtimestamp[32] = {0};
GetTimeNet(localtimestamp, 1);
// 接收到原始数据信息,则更新时间戳,如果三秒种未收到原始数据,则重新从短地址 9999 切换回 短地址 8888
m_TimeStamp = strtol(localtimestamp, NULL, 10);
}
void Uart::DealWaveThread() {
while (1) {
DealWave();
sleep(1);
}
}
std::vector<float> Uart::DealData(int iChannel, float coe, int sampleRate, int ACCSampleTime, string strProduct) {
int waveCount = 0;
unsigned char data[1024 * 100] = {0x00};
unsigned char outdata[1024 * 100] = {0x00};
unsigned char dealdata[1024 * 100] = {0x00};
long unsigned int new_len = 0, deallen = 0;
int compress = 0, count = 0;
long iTemp = 0;
char buf[8] = {0x00};
std::vector<float> vecData;
print_info("data1 = %02x\n", g_VecWaveDataX[0].Data[0]);
print_info("data2 = %02x\n", g_VecWaveDataY[0].Data[0]);
print_info("data3 = %02x\n", g_VecWaveDataZ[0].Data[0]);
size_t j = 0;
std::string strShortAddr = "";
if (iChannel == 3) {
if (VecWaveDataX.size() > 0) {
g_VecWaveDataX.assign(VecWaveDataX.begin(), VecWaveDataX.end());
waveCount = VecWaveDataX.size();
}
waveCount = m_waveCountX;
for (; j < waveCount; j++) {
RecvData recvData = g_VecWaveDataX[j];
memcpy(data + j * 92, recvData.Data, 92);
}
memset(buf, 0x00, sizeof(buf));
sprintf(buf, "%02x%02x", g_VecWaveDataX[0].ShortAddr[0], g_VecWaveDataX[0].ShortAddr[1]);
strShortAddr = std::string(buf);
compress = g_mapCompress[strShortAddr].compressChannelX;
count = g_mapCompress[strShortAddr].CountX;
}
if (iChannel == 4) {
if (VecWaveDataY.size() > 0) {
g_VecWaveDataY.assign(VecWaveDataY.begin(), VecWaveDataY.end());
waveCount = VecWaveDataY.size();
}
waveCount = m_waveCountY;
for (; j < waveCount; j++) {
RecvData recvData = g_VecWaveDataY[j];
memcpy(data + j * 92, recvData.Data, 92);
}
memset(buf, 0x00, sizeof(buf));
sprintf(buf, "%02x%02x", g_VecWaveDataY[0].ShortAddr[0], g_VecWaveDataY[0].ShortAddr[1]);
strShortAddr = std::string(buf);
compress = g_mapCompress[strShortAddr].compressChannelY;
count = g_mapCompress[strShortAddr].CountY;
}
if (iChannel == 5) {
if (VecWaveDataZ.size() > 0) {
g_VecWaveDataZ.assign(VecWaveDataZ.begin(), VecWaveDataZ.end());
waveCount = VecWaveDataZ.size();
}
waveCount = m_waveCountZ;
for (; j < waveCount; j++) {
RecvData recvData = g_VecWaveDataZ[j];
memcpy(data + j * 92, recvData.Data, 92);
}
memset(buf, 0x00, sizeof(buf));
sprintf(buf, "%02x%02x", g_VecWaveDataZ[0].ShortAddr[0], g_VecWaveDataZ[0].ShortAddr[1]);
strShortAddr = std::string(buf);
compress = g_mapCompress[strShortAddr].compressChannelZ;
count = g_mapCompress[strShortAddr].CountZ;
}
print_info("len = %d,data = %02x,iChannel = %d,compress = %d,count = %d\n", j, data[0], iChannel, compress, count);
if (j * 92 < count) return vecData;
if (compress) {
print_info("iChannel = %d,compress = %d\n", iChannel, compress);
int r = lzo1x_decompress(data, count, outdata, &new_len, NULL);
print_info("lzo1x_decompress end\n");
if (r == LZO_E_OK) {
printf("decompressed %lu bytes back into %lu bytes\n", (unsigned long)j * 92, (unsigned long)new_len);
LOG_INFO("iChannel = %d ,ShortAddr = %s decompressed %lu bytes back into %lu bytes\n", iChannel, strShortAddr.c_str(), (unsigned long)j * 92, (unsigned long)new_len);
} else {
/* this should NEVER happen */
printf("internal error - decompression failed: %d\n", r);
LOG_ERROR("internal error - decompression failed: %d,channel = %d,ShortAddr = %s\n", r, iChannel, strShortAddr.c_str());
return vecData;
}
memcpy(dealdata, outdata, new_len);
deallen = new_len;
} else {
memcpy(dealdata, data, j * 92);
deallen = j * 92;
}
print_info("len = %d,dealdata = %02x\n", deallen, dealdata[0]);
for (int i = 0; i < deallen; i++) {
float fTemp = 0.0;
memset(buf, 0, 8);
sprintf(buf, "%02x%02x", dealdata[2 * i + 1], dealdata[i * 2]);
iTemp = strtol(buf, NULL, 16);
if (iTemp < 0x8000) {
fTemp = iTemp * coe * 9.8; // convert to m/s2
} else {
fTemp = (((~iTemp) & 0xffff) + 1) * -coe * 9.8; // convert to m/s2
}
vecData.push_back(fTemp);
if (strProduct == "01") {
if (vecData.size() == sampleRate * ACCSampleTime && iChannel == 3) { //过滤数据包结尾空数据
print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n", iChannel, vecData.size(), sampleRate * ACCSampleTime);
break;
}
if (vecData.size() == sampleRate * ACCSampleTime && iChannel == 4) { //过滤数据包结尾空数据
print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n", iChannel, vecData.size(), sampleRate * ACCSampleTime);
break;
}
if (vecData.size() == sampleRate * ACCSampleTime && iChannel == 5) { //过滤数据包结尾空数据
print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n", iChannel, vecData.size(), sampleRate * ACCSampleTime);
break;
}
} else if (strProduct == "02") {
if (vecData.size() == 8192 && iChannel == 3) { //过滤数据包结尾空数据
break;
}
if (vecData.size() == 8192 && iChannel == 4) { //过滤数据包结尾空数据
break;
}
if (vecData.size() == sampleRate * ACCSampleTime && iChannel == 5) { //过滤数据包结尾空数据
break;
}
}
}
return vecData;
}
void Uart::DealWave() {
std::string strShortAddr = "";
std::string strShortAddrTemp;
std::string strLongAddr = "";
std::string strMeasurementID = "";
std::string strFileName = "";
std::string strProduct = "";
int iChannel = 0;
int iChannelTemp = 0;
std::vector<float> vecData;
RecvData recvTemp;
if (wave_trans_) { //对每个传感器的每个通道进行遍历然后处理数据例如传感器1x轴的数据处理完后再去处理y轴的。传感器1的所有数据处理完后再处理传感器2的
char getLongAddr_sql[32] = {0};
sprintf(getLongAddr_sql, "zigbeeShortAddr='%s'", m_strDestShortAddr.c_str());
vec_t res = sqlite_db_ctrl::instance().GetDataSingleLine(T_SENSOR_INFO(TNAME), " * ", getLongAddr_sql);
strLongAddr = res[0];
strMeasurementID = res[44];
if (0 == strLongAddr.length()) {
sleep(1);
return;
}
std::string ran = "";
int n = 0;
int range = 0;
float coe = 0;
int sampleRate = 0, ACCSampleTime = 0;
char getrange[32] = {0};
std::string str = "range";
sprintf(getrange, "zigbeeShortAddr='%s'", strShortAddr.c_str());
ran = res[25];
sampleRate = atoi(res[23].c_str());
ACCSampleTime = atoi(res[36].c_str());
strProduct = res[17];
memset(getrange, 0, 32);
sprintf(getrange, "%s", ran.c_str());
n = (int)strtol(getrange, NULL, 32);
if (m_waveCountX > 0 || VecWaveDataX.size() > 0) {
print_info("m_waveCountX = %d,VecWaveData = %d\n", m_waveCountX, VecWaveDataX.size());
coe = Calcoe(n, 3, strProduct, range);
vecData = DealData(3, coe, sampleRate, ACCSampleTime, strProduct);
WriteDatFile(sampleRate, strMeasurementID, 3, vecData);
m_waveCountX = 0;
g_VecWaveDataX.clear();
VecWaveDataX.clear();
}
if (m_waveCountY > 0 || VecWaveDataY.size() > 0) {
print_info("m_waveCountY = %d,VecWaveData = %d\n", m_waveCountY, VecWaveDataY.size());
coe = Calcoe(n, 4, strProduct, range);
vecData = DealData(4, coe, sampleRate, ACCSampleTime, strProduct);
WriteDatFile(sampleRate, strMeasurementID, 4, vecData);
m_waveCountY = 0;
g_VecWaveDataY.clear();
VecWaveDataY.clear();
}
if (m_waveCountZ > 0 || VecWaveDataZ.size() > 0) {
print_info("m_waveCountZ = %d,VecWaveDataZ = %d\n", m_waveCountZ, VecWaveDataZ.size());
coe = Calcoe(n, 5, strProduct, range);
vecData = DealData(5, coe, sampleRate, ACCSampleTime, strProduct);
WriteDatFile(sampleRate, strMeasurementID, 5, vecData);
m_waveCountZ = 0;
g_VecWaveDataZ.clear();
VecWaveDataZ.clear();
}
char whereCon[1024] = {0x00};
char updateSql[1024] = {0x00};
sprintf(whereCon, "dataNodeNo='%s'", strLongAddr.c_str());
sprintf(updateSql, "WaveTime = WaveTime + 1");
sqlite_db_ctrl::instance().UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon);
wave_trans_ = false;
}
}
float Uart::Calcoe(int ran, int iChannel, string &product, int range) {
float coe = 0.0;
if (product == "01") {
switch (ran) {
case 0: {
range = 8;
coe = 8 * 1.0 / 32767;
} break;
case 1: {
range = 16;
coe = 16 * 1.0 / 32767;
} break;
case 2: {
range = 32;
coe = 32 * 1.0 / 32767;
} break;
case 3: {
range = 64;
coe = 64 * 1.0 / 32767;
} break;
}
} else if (product == "02") {
if (iChannel == 3 || iChannel == 4) {
coe = 0.00048828125;
}
if (iChannel == 5) {
/*if(res[8] == "0.1"){
coe = 0.0034521484375;//0.03265968810083316;
}else*/
{ coe = 0.00172607421875; }
}
}
return coe;
}
void Uart::WriteDatFile(int sampleRate, string &strMeasurementID, int iChannel, std::vector<float> &vecData) {
if (vecData.size() <= 0) return;
std::string strFileName = "";
char localtimestamp[32] = {0};
GetTimeNet(localtimestamp, 1);
std::string nowTimetamp = std::string(localtimestamp);
std::string strChannelID = "";
switch (iChannel) {
case 3: {
strFileName = "/opt/data/" + strMeasurementID + "-X.dat";
strChannelID = strMeasurementID + "-X";
} break;
case 4: {
strFileName = "/opt/data/" + strMeasurementID + "-Y.dat";
strChannelID = strMeasurementID + "-Y";
} break;
case 5: {
strFileName = "/opt/data/" + strMeasurementID + "-Z.dat";
strChannelID = strMeasurementID + "-Z";
} break;
default: break;
}
if (access(strFileName.c_str(), 0) > 0) { //如果存在原始数据删除原来的,只保留一份
std::string strCmd = "rm " + strFileName;
system(strCmd.c_str());
}
FILE *fp = fopen(strFileName.c_str(), "w");
fwrite(localtimestamp, sizeof(localtimestamp), 1, fp);
print_info("fopen FIle vecData.size : %d\n", vecData.size());
float mean = Calculation::mean(vecData);
float frTemp;
char buf[33] = {0x00};
std::string strWaveData = "";
for (int i = 0; i < vecData.size(); i++) {
frTemp = vecData[i] - mean;
fwrite(&frTemp, sizeof(float), 1, fp);
memset(buf, 0x00, sizeof(buf));
sprintf(buf, "%.2f", frTemp);
std::string waveTemp(buf);
if (i == 0)
strWaveData = waveTemp;
else
strWaveData = strWaveData + "," + waveTemp;
if (i % 100 == 0) {
mssleep(5000);
}
}
fclose(fp);
//
Json::Value valWaveData;
int length = vecData.size();
valWaveData["number"] = sampleRate;
valWaveData["channelId"] = strChannelID;
valWaveData["dataNodeNo"] = strMeasurementID;
valWaveData["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G;
valWaveData["SensorEngineeringUnit"] = "";
valWaveData["timeStamp"] = nowTimetamp;
valWaveData["waveData"] = strWaveData;
valWaveData["mean"] = mean;
Json::FastWriter WaveValue;
std::string WaveData = WaveValue.write(valWaveData);
char selectCon[128] = {0};
sprintf(selectCon, "channelID='%s' ORDER BY timeStamp ASC LIMIT 0,1", strChannelID.c_str());
std::string strTime = sqlite_db_ctrl::instance().GetData("t_data_waveSend", "timeStamp", selectCon);
long lTime = atol(nowTimetamp.c_str()) - atol(strTime.c_str());
int Count = sqlite_db_ctrl::instance().GetTableRows("t_data_waveSend", NULL);
std::string strFileName_Record = strFileName + "_" + nowTimetamp;
if ((Count * 3 < SAVE_COUNT && lTime < OneWeek) || strTime.size() == 0) {
char insertSql[128] = {0x00};
sprintf(insertSql, "'%s','%s','%s',1,0", strChannelID.c_str(), strFileName_Record.c_str(), nowTimetamp.c_str());
sqlite_db_ctrl::instance().InsertData("t_data_waveSend", insertSql);
} else {
char updateSql[128] = {0}, whereCon[128] = {0};
sprintf(updateSql, "waveName='%s',timeStamp='%s'", strFileName_Record.c_str(), nowTimetamp.c_str());
memset(whereCon, 0x00, sizeof(whereCon));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s'", strChannelID.c_str(), strTime.c_str());
print_info("update static data to sql\n");
sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, whereCon);
}
//传感器发来的数据包中的表示设备信息的数据转化为json格式后通过调用data_publish将数据传给mqttclient Topicwireless/cmd/60294D203717
int iRet = data_publish(WaveData.c_str(), GlobalConfig::Topic_G.mPubWaveData.c_str());
if (iRet != 0) {
char whereCon[1024] = {0x00};
char updateSql[1024] = {0x00};
char tmpWhere[128] = {0x00};
sprintf(tmpWhere, "channelID = '%s' and sendMsg = 0 ", strChannelID.c_str());
int count = sqlite_db_ctrl::instance().GetTableRows("t_data_waveSend", tmpWhere);
LOG_ERROR("save channlID %s dat count = %d\n", strChannelID.c_str(), count);
if (count <= 12) {
sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(), nowTimetamp.c_str());
sprintf(updateSql, "SendMsg = 0 ");
sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, whereCon);
LOG_ERROR("send failed,filename %s,iRet = %d\n", strFileName.c_str(), iRet);
string strFileName_failed = strFileName + "_" + nowTimetamp;
char tmpCmd[128] = {0x00};
sprintf(tmpCmd, "cp %s %s", strFileName.c_str(), strFileName_failed.c_str());
system(tmpCmd);
} else {
memset(tmpWhere, 0x00, sizeof(tmpWhere));
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(tmpWhere, " sendMsg = 0 and channelID='%s' ORDER BY timeStamp ASC LIMIT 0,1", strChannelID.c_str());
vec_t vecRet = sqlite_db_ctrl::instance().GetDataSingleLine("t_data_waveSend", "*", tmpWhere);
memset(tmpWhere, 0x00, sizeof(tmpWhere));
sprintf(tmpWhere, " sendMsg = 0 and timeStamp = '%s' and channelID = '%s' ", vecRet[2].c_str(), vecRet[0].c_str());
sprintf(updateSql, "sendMsg = 3 ");
int iRet = sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, tmpWhere);
memset(tmpWhere, 0x00, sizeof(tmpWhere));
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(), nowTimetamp.c_str());
sprintf(updateSql, "sendMsg = 0");
int iRet2 = sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, whereCon);
string strFileName_failed = strFileName + "_" + nowTimetamp;
char tmpCmd[128] = {0x00};
sprintf(tmpCmd, "cp %s %s", strFileName.c_str(), strFileName_failed.c_str());
system(tmpCmd);
LOG_ERROR("cp dat file %s \n", tmpCmd);
memset(tmpWhere, 0x00, sizeof(tmpWhere));
sprintf(tmpWhere, " channelID = '%s' and sendMsg = 0 ", strChannelID.c_str());
int count = sqlite_db_ctrl::instance().GetTableRows("t_data_waveSend", tmpWhere);
memset(tmpCmd, 0x00, sizeof(tmpCmd));
sprintf(tmpCmd, "rm %s ", vecRet[1].c_str());
system(tmpCmd);
LOG_ERROR("rm dat file %s \n", tmpCmd);
}
} else {
LOG_DEBUG("send data , filename %s,size = %d\n", strFileName.c_str(), vecData.size());
}
#ifdef G2UL_GATEWAY //存储6条波形数据
char whereCon[1024] = {0x00};
char updateSql[1024] = {0x00};
char tmpWhere[128] = {0x00};
sprintf(tmpWhere, "channelID = '%s' and save = 1 ", strChannelID.c_str());
int count = sqlite_db_ctrl::instance().GetTableRows("t_data_waveSend", tmpWhere);
LOG_INFO("save channlID %s dat count = %d\n", strChannelID.c_str(), count);
if (count <= 5) {
sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(), nowTimetamp.c_str());
sprintf(updateSql, "save = 1 ");
sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, whereCon);
string strFileName_save = strFileName + "_" + nowTimetamp + "_save";
char tmpCmd[128] = {0x00};
sprintf(tmpCmd, "cp %s %s", strFileName.c_str(), strFileName_save.c_str());
system(tmpCmd);
} else {
memset(tmpWhere, 0x00, sizeof(tmpWhere));
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(tmpWhere, " save = 1 and channelID='%s' ORDER BY timeStamp ASC LIMIT 0,1", strChannelID.c_str());
vec_t vecRet = sqlite_db_ctrl::instance().GetDataSingleLine("t_data_waveSend", "*", tmpWhere);
memset(tmpWhere, 0x00, sizeof(tmpWhere));
sprintf(tmpWhere, " save = 1 and timeStamp = '%s' and channelID = '%s' ", vecRet[2].c_str(), vecRet[0].c_str());
sprintf(updateSql, "save = 0 ");
int iRet = sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, tmpWhere);
memset(tmpWhere, 0x00, sizeof(tmpWhere));
memset(updateSql, 0x00, sizeof(updateSql));
sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(), nowTimetamp.c_str());
sprintf(updateSql, "save = 1");
int iRet2 = sqlite_db_ctrl::instance().UpdateTableData("t_data_waveSend", updateSql, whereCon);
string strFileName_save = strFileName + "_" + nowTimetamp + "_save";
char tmpCmd[128] = {0x00};
sprintf(tmpCmd, "cp %s %s", strFileName.c_str(), strFileName_save.c_str());
system(tmpCmd);
memset(tmpWhere, 0x00, sizeof(tmpWhere));
sprintf(tmpWhere, " channelID = '%s' and save = 1 ", strChannelID.c_str());
int count = sqlite_db_ctrl::instance().GetTableRows("t_data_waveSend", tmpWhere);
memset(tmpCmd, 0x00, sizeof(tmpCmd));
sprintf(tmpCmd, "rm %s ", (vecRet[1] + "_save").c_str());
system(tmpCmd);
LOG_INFO("rm dat file %s \n", tmpCmd);
}
#endif
print_info("write data to filename %s\n", strFileName.c_str());
std::vector<float>().swap(vecData);
sleep(1);
}