This commit is contained in:
jfmartel 2020-10-09 07:05:31 -04:00
parent 02e968c724
commit 8d1fa787e4
14 changed files with 299 additions and 25 deletions

View File

@ -1,6 +1,7 @@
#QT += Network #QT += Network
#QT += gui declarative network #QT += gui declarative network
QT += gui network serialport QT += gui network serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
#CONFIG += console #CONFIG += console
@ -37,7 +38,10 @@ HEADERS += \
Sources/Sprinkler/SprinklerMgr.h \ Sources/Sprinkler/SprinklerMgr.h \
Sources/AvReceiver/AvReceiverInterface.h \ Sources/AvReceiver/AvReceiverInterface.h \
Sources/AvReceiver/AvReceiverData.h \ Sources/AvReceiver/AvReceiverData.h \
Sources/Chalet/ChaletNetworkMessage.h Sources/Chalet/ChaletNetworkMessage.h \
Sources/HttpServer/HttpServer.h \
Sources/BlynkCloudClient.h \
Sources/Chalet/ChaletDataLogger.h
SOURCES += \ SOURCES += \
Sources/Chalet/ChaletData.cpp \ Sources/Chalet/ChaletData.cpp \
@ -70,7 +74,10 @@ SOURCES += \
Sources/Sprinkler/SprinklerMgr.cpp \ Sources/Sprinkler/SprinklerMgr.cpp \
Sources/AvReceiver/AvReceiverInterface.cpp \ Sources/AvReceiver/AvReceiverInterface.cpp \
Sources/AvReceiver/AvReceiverData.cpp \ Sources/AvReceiver/AvReceiverData.cpp \
Sources/Chalet/ChaletNetworkMessage.cpp Sources/Chalet/ChaletNetworkMessage.cpp \
Sources/HttpServer/HttpServer.cpp \
Sources/BlynkCloudClient.cpp \
Sources/Chalet/ChaletDataLogger.cpp
DEFINES -= Q_OS_UNIX DEFINES -= Q_OS_UNIX
@ -87,7 +94,10 @@ INCLUDEPATH += $$PWD/ \
$$PWD/Sources/Sprinkler \ $$PWD/Sources/Sprinkler \
$$PWD/Sources/AvReceiver \ $$PWD/Sources/AvReceiver \
$$PWD/Sources/Chalet \ $$PWD/Sources/Chalet \
$$PWD/Sources/HttpServer \
$$PWD/blynk-library-master/src/ \
FORMS += FORMS +=
DISTFILES += DISTFILES += \
../../../../Dev/qthttpserver/mkspecs/modules/qt_lib_httpserver.pri

View File

@ -0,0 +1,109 @@
#include "BlynkCloudClient.h"
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
CBlynkCloudClient::CBlynkCloudClient()
{
mBlynkSocket = new QNetworkAccessManager;
connect(mBlynkSocket,SIGNAL(finished(QNetworkReply*)),this,SLOT(BlynkServerFinished(QNetworkReply*)));
connect(mBlynkSocket,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),this,SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
mDummy = 0;
}
void CBlynkCloudClient::TestBlynk()
{
//QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/update/V0?value=%1").arg(mDummy++);
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/get/V10");
mBlynkSocket->get(QNetworkRequest(URL));
}
void CBlynkCloudClient::UpdateChaletCurrent(int Current)
{
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/update/V1?value=%1").arg(Current);
mBlynkSocket->get(QNetworkRequest(URL));
}
void CBlynkCloudClient::UpdateChaletVoltage(float Voltage)
{
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/update/V0?value=%1").arg(Voltage);
mBlynkSocket->get(QNetworkRequest(URL));
}
void CBlynkCloudClient::UpdateChaletWifiStatus(int Status)
{
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/update/V10?value=%1").arg(Status);
mBlynkSocket->get(QNetworkRequest(URL));
}
void CBlynkCloudClient::UpdateChaletInverterStatus(int Status)
{
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/update/V10?value=%1").arg(Status);
mBlynkSocket->get(QNetworkRequest(URL));
}
void CBlynkCloudClient::UpdateChaletStatusLed(int Status)
{
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/update/V12?value=%1").arg(Status);
mBlynkSocket->get(QNetworkRequest(URL));
}
int CBlynkCloudClient::GetChaletWifiToggleSwitchStatus()
{
// http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/get/V10
QString URL = QString("http://blynk-cloud.com/NzI2kH0L0sLOO8NWyPyoZPS7IFJ3Gtho/get/V10");
mBlynkSocket->get(QNetworkRequest(URL));
}
void CBlynkCloudClient::BlynkServerFinished(QNetworkReply *NetworkReply)
{
if(NetworkReply->isFinished() == false)
return;
if(NetworkReply->error() != QNetworkReply::NoError)
{
qDebug("Network error... %d", NetworkReply->error());
return;
}
QByteArray Reply = NetworkReply->readAll();
if(Reply.isEmpty())
return;
NetworkReply->deleteLater();
QString ReplyString(Reply);
ReplyString.remove("[\"");
ReplyString.remove("\"]");
QJsonValue Result(ReplyString);
// QJsonParseError error;
// QJsonDocument JsonReply = QJsonDocument::fromJson(Reply,&error);
// QJsonObject JsonObject = JsonReply.object();
// QStringList Keys = JsonObject.keys();
int toto = ReplyString.toInt();
qDebug("Switch = %d",toto);
}
void CBlynkCloudClient::sslErrors(QNetworkReply *reply, QList<QSslError> error)
{
qDebug("Ssl errors...");
reply->ignoreSslErrors();
}

View File

@ -0,0 +1,32 @@
#ifndef BLYNKCLOUDCLIENT_H
#define BLYNKCLOUDCLIENT_H
#include <QObject>
#include <QNetworkAccessManager>
class CBlynkCloudClient : public QObject
{
Q_OBJECT
public:
CBlynkCloudClient();
void TestBlynk();
void UpdateChaletVoltage(float Voltage);
void UpdateChaletCurrent(int Current);
void UpdateChaletWifiStatus(int Status);
void UpdateChaletInverterStatus(int Status);
void UpdateChaletStatusLed(int Status);
int GetChaletWifiToggleSwitchStatus();
int mDummy;
private:
QNetworkAccessManager *mBlynkSocket;
public slots:
void BlynkServerFinished(QNetworkReply*);
void sslErrors(QNetworkReply*,QList<QSslError>);
};
#endif // BLYNKCLOUDCLIENT_H

View File

@ -5,10 +5,12 @@ CChaletMainStatus::CChaletMainStatus()
{ {
mInverterRelayStatus = UNKNOWN_STATE; mInverterRelayStatus = UNKNOWN_STATE;
mWiFiModuleStatus = UNKNOWN_STATE; mWiFiModuleStatus = UNKNOWN_STATE;
mCurrentSensorStatus = UNKNOWN_STATE;
mBatteryCurrent = 0; mBatteryCurrent = 0;
mBatteryVoltage = 0; mBatteryVoltage = 0;
mIsOnline = false; mIsOnline = false;
mHarakiriDone = false; mHarakiriDone = false;
mStatusToggleBit = 0;
} }
@ -48,6 +50,8 @@ QByteArray CChaletMainStatus::ToByteArray()
Strm << mBatteryVoltage; Strm << mBatteryVoltage;
Strm << mBatteryCurrent; Strm << mBatteryCurrent;
Strm << mBatterySOC; Strm << mBatterySOC;
Strm << mIsOnline;
Strm << mCurrentSensorStatus;
return Data; return Data;
} }

View File

@ -18,14 +18,17 @@ public:
quint8 mInverterRelayStatus; quint8 mInverterRelayStatus;
quint8 mWiFiModuleStatus; quint8 mWiFiModuleStatus;
qint8 mCurrentSensorStatus;
float mBatteryVoltage; float mBatteryVoltage;
float mBatteryCurrent; qint16 mBatteryCurrent;
float mBatterySOC; qint16 mBatterySOC;
bool mHarakiriDone; bool mHarakiriDone;
bool mIsOnline; bool mIsOnline;
bool mStatusToggleBit;
QDateTime mLastLoraStatus; QDateTime mLastLoraStatus;
}; };

View File

@ -0,0 +1,6 @@
#include "ChaletDataLogger.h"
CChaletDataLogger::CChaletDataLogger(QObject *parent) : QObject(parent)
{
}

View File

@ -0,0 +1,17 @@
#ifndef CHALETDATALOGGER_H
#define CHALETDATALOGGER_H
#include <QObject>
class CChaletDataLogger : public QObject
{
Q_OBJECT
public:
explicit CChaletDataLogger(QObject *parent = 0);
signals:
public slots:
};
#endif // CHALETDATALOGGER_H

View File

@ -2,6 +2,7 @@
#include "GlobalDefine.h" #include "GlobalDefine.h"
CChaletLoraDevice::CChaletLoraDevice(int Address, CAbstractNetworkCommIF *NetworkInterface): CChaletLoraDevice::CChaletLoraDevice(int Address, CAbstractNetworkCommIF *NetworkInterface):
CNetworkDevice(ID_CHALET_DEVICE,Address,NetworkInterface) CNetworkDevice(ID_CHALET_DEVICE,Address,NetworkInterface)
{ {
@ -40,10 +41,15 @@ int CChaletLoraDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, i
case CHALET_GENERAL_STATUS_RESPONSE: case CHALET_GENERAL_STATUS_RESPONSE:
{ {
float temp; float temp;
qint16 temp2;
qDebug("Chalet Status RX"); qDebug("Chalet Status RX");
char VoltageArray[4]; char VoltageArray[4];
char SolarPanelCurrentArray[2];
char BatterySOCArray[2];
mChaletMainStatus.mInverterRelayStatus = ((Data[0] & LORA_CHALET_STATUS_POWER_RELAY_MASK) != 0);
mChaletMainStatus.mCurrentSensorStatus = ((Data[0] & LORA_CHALET_STATUS_CUR_SENSOR_MASK) != 0);
mChaletMainStatus.mInverterRelayStatus = Data[0];
mChaletMainStatus.mWiFiModuleStatus = Data[1]; mChaletMainStatus.mWiFiModuleStatus = Data[1];
VoltageArray[0] = Data[2]; VoltageArray[0] = Data[2];
VoltageArray[1] = Data[3]; VoltageArray[1] = Data[3];
@ -51,8 +57,30 @@ int CChaletLoraDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, i
VoltageArray[3] = Data[5]; VoltageArray[3] = Data[5];
memcpy(&temp,VoltageArray,4); memcpy(&temp,VoltageArray,4);
mChaletMainStatus.mBatteryVoltage = temp; mChaletMainStatus.mBatteryVoltage = temp;
SolarPanelCurrentArray[0] = Data[6];
SolarPanelCurrentArray[1] = Data[7];
memcpy(&temp2,SolarPanelCurrentArray,2);
mChaletMainStatus.mBatteryCurrent = temp2;
BatterySOCArray[0] = Data[8];
BatterySOCArray[1] = Data[9];
memcpy(&temp2,BatterySOCArray,2);
mChaletMainStatus.mBatterySOC = temp2;
mChaletMainStatus.mStatusToggleBit = !mChaletMainStatus.mStatusToggleBit;
CmdResponseReceived(CHALET_GENERAL_STATUS_REQUEST); CmdResponseReceived(CHALET_GENERAL_STATUS_REQUEST);
qDebug("voltage: %f",mChaletMainStatus.mBatteryVoltage); qDebug("voltage: %f",mChaletMainStatus.mBatteryVoltage);
qDebug("Current: %d",mChaletMainStatus.mBatteryCurrent);
qDebug("SOC: %d",mChaletMainStatus.mBatterySOC);
mBlynkInterface.UpdateChaletCurrent(mChaletMainStatus.mBatteryCurrent);
mBlynkInterface.UpdateChaletVoltage(mChaletMainStatus.mBatteryVoltage);
// mBlynkInterface.UpdateChaletWifiStatus((int)mChaletMainStatus.mInverterRelayStatus);
mBlynkInterface.UpdateChaletInverterStatus((int)mChaletMainStatus.mInverterRelayStatus);
mBlynkInterface.UpdateChaletStatusLed(((int)mChaletMainStatus.mStatusToggleBit)*255);
break; break;
} }
case CHALET_AC_POWER_STATE_STATUS_RESPONSE: case CHALET_AC_POWER_STATE_STATUS_RESPONSE:
@ -134,21 +162,27 @@ void CChaletLoraDevice::CommTimerExpired()
{ {
qDebug("Empty command list in comm timer "); qDebug("Empty command list in comm timer ");
ScheduleChaletStatusRequest(); ScheduleChaletStatusRequest();
mChaletStatusTimer->start(1000); mChaletStatusTimer->start(LORA_NORMAL_REQUEST_TIMEOUT);
return; return;
} }
if(mPendingNetworkMsgList.first().PendingResponse == true) if(mPendingNetworkMsgList.first().PendingResponse == true)
{ {
//The current command is still waiting for a response. Check how many times we tried to send it //The current command is still waiting for a response. Check how many times we tried to send it
qDebug("Cmd 0x%x timetout... retrying",mPendingNetworkMsgList.first().mMessageID); qDebug("Cmd 0x%x timetout... retrying",mPendingNetworkMsgList.first().mMessageID);
if(mPendingNetworkMsgList.first().ResendCounter >= 5) if(mPendingNetworkMsgList.first().ResendCounter >= 2)
{ {
//TODO: manage this. Module offline? //After 2 retries, declare module offline, clear the send buffer and start sending status requests...
} if(mChaletMainStatus.mIsOnline == true)
else {
{ mChaletMainStatus.mIsOnline = false;
mPendingNetworkMsgList[0].ResendCounter++; qDebug("Chalet LORA interface Offline. Switching to status requests...");
mPendingNetworkMsgList.clear();
ScheduleChaletStatusRequest();
mPendingNetworkMsgList.first().ResendCounter = 2;
}
} }
mPendingNetworkMsgList[0].ResendCounter++;
} }
qDebug("Sending chalet request 0x%x",mPendingNetworkMsgList.at(0).mMessageID); qDebug("Sending chalet request 0x%x",mPendingNetworkMsgList.at(0).mMessageID);
@ -164,7 +198,7 @@ void CChaletLoraDevice::CommTimerExpired()
ScheduleChaletStatusRequest(); ScheduleChaletStatusRequest();
} }
mChaletStatusTimer->start(5000); //we should get an answer within 5 seconds. mChaletStatusTimer->start(LORA_RESPONSE_TIME_TIMEOUT); //we should get an answer within 5 seconds.
// SendChaletCommand(CHALET_GENERAL_STATUS_REQUEST,0,QByteArray()); // SendChaletCommand(CHALET_GENERAL_STATUS_REQUEST,0,QByteArray());
} }
@ -181,8 +215,7 @@ int CChaletLoraDevice::SendWiFiModuleSetState(bool State)
Data[0] = 0; Data[0] = 0;
} }
ScheduleChaletCommand(CHALET_WIFI_SET_STATE_REQUEST,1,Data); return ScheduleChaletCommand(CHALET_WIFI_SET_STATE_REQUEST,1,Data);
return RET_OK;
} }
int CChaletLoraDevice::SendInverterPowerRelayState(bool State) int CChaletLoraDevice::SendInverterPowerRelayState(bool State)
@ -198,9 +231,7 @@ int CChaletLoraDevice::SendInverterPowerRelayState(bool State)
Data[0] = 0; Data[0] = 0;
} }
ScheduleChaletCommand(CHALET_AC_POWER_SET_STATE_REQUEST,Data); return ScheduleChaletCommand(CHALET_AC_POWER_SET_STATE_REQUEST,Data);
// SendChaletCommand(CHALET_AC_POWER_SET_STATE_REQUEST,1,Data);
return RET_OK;
} }
int CChaletLoraDevice::SendDOHarakiri() int CChaletLoraDevice::SendDOHarakiri()
@ -212,7 +243,7 @@ int CChaletLoraDevice::SendDOHarakiri()
Data.append(0xBE); Data.append(0xBE);
Data.append(0xEF); Data.append(0xEF);
ScheduleChaletCommand(CHALET_DO_HARAKIRI_REQUEST,Data); return ScheduleChaletCommand(CHALET_DO_HARAKIRI_REQUEST,Data);
} }
int CChaletLoraDevice::SendRebootCmd() int CChaletLoraDevice::SendRebootCmd()
@ -224,7 +255,7 @@ int CChaletLoraDevice::SendRebootCmd()
Data.append(0xCA); Data.append(0xCA);
Data.append(0xFE); Data.append(0xFE);
ScheduleChaletCommand(CHALET_REBOOT_CPU_REQUEST,Data); return ScheduleChaletCommand(CHALET_REBOOT_CPU_REQUEST,Data);
} }
int CChaletLoraDevice::SendChaletCommand(int CmdID, int DataSize, QByteArray Data) int CChaletLoraDevice::SendChaletCommand(int CmdID, int DataSize, QByteArray Data)
@ -237,6 +268,12 @@ int CChaletLoraDevice::CmdResponseReceived(int CmdID)
{ {
Q_UNUSED(CmdID) Q_UNUSED(CmdID)
if(mChaletMainStatus.mIsOnline == false)
{
mChaletMainStatus.mIsOnline = true;
qDebug("Chalet is ONLINE!");
}
qDebug("Chalet response received from cmd: 0x%x",CmdID); qDebug("Chalet response received from cmd: 0x%x",CmdID);
if(mPendingNetworkMsgList.size() == 0) if(mPendingNetworkMsgList.size() == 0)
{ {
@ -266,20 +303,46 @@ int CChaletLoraDevice::CmdResponseReceived(int CmdID)
int CChaletLoraDevice::ScheduleChaletStatusRequest() int CChaletLoraDevice::ScheduleChaletStatusRequest()
{ {
ScheduleChaletCommand(CHALET_GENERAL_STATUS_REQUEST,0,QByteArray()); return ScheduleChaletCommand(CHALET_GENERAL_STATUS_REQUEST,0,QByteArray());
} }
int CChaletLoraDevice::ScheduleChaletCommand(int CmdID, int DataSize, QByteArray Data) int CChaletLoraDevice::ScheduleChaletCommand(int CmdID, int DataSize, QByteArray Data)
{ {
Q_UNUSED(DataSize) Q_UNUSED(DataSize)
CChaletNetworkMessage Command(CmdID,Data);
mPendingNetworkMsgList.append(Command); // if(mChaletMainStatus.mIsOnline == false)
// {
// return RET_ERROR;
// }
// CChaletNetworkMessage Command(CmdID,Data);
// mPendingNetworkMsgList.append(Command);
ScheduleChaletCommand(CmdID,Data);
return RET_OK; return RET_OK;
} }
int CChaletLoraDevice::ScheduleChaletCommand(int CmdID, QByteArray Data) int CChaletLoraDevice::ScheduleChaletCommand(int CmdID, QByteArray Data)
{ {
// if(mChaletMainStatus.mIsOnline == false)
// {
// return RET_ERROR;
// }
if(mChaletMainStatus.mIsOnline == true && CmdID != CHALET_GENERAL_STATUS_REQUEST) //When chalet is online, send command right away if we are not waiting for an answer.
{
//if we are in nominal conditions (waiting to send a status request). Cancel the status request and send the command right away.
if((mPendingNetworkMsgList.size() == 1) &&
(mPendingNetworkMsgList.at(0).mMessageID == CHALET_GENERAL_STATUS_REQUEST) &&
mPendingNetworkMsgList.at(0).PendingResponse == false)
{
mPendingNetworkMsgList.clear();
mChaletStatusTimer->start(10); //Allow some time to breathe
}
}
CChaletNetworkMessage Command(CmdID,Data); CChaletNetworkMessage Command(CmdID,Data);
mPendingNetworkMsgList.append(Command); mPendingNetworkMsgList.append(Command);

View File

@ -9,8 +9,16 @@
#include "ChaletData.h" #include "ChaletData.h"
#include "ChaletNetworkMessage.h" #include "ChaletNetworkMessage.h"
#include <QList> #include <QList>
#include "BlynkCloudClient.h"
#define LORA_MAGIC_WORD 0xBAADCAFE #define LORA_MAGIC_WORD 0xBAADCAFE
#define LORA_NORMAL_REQUEST_TIMEOUT 1000
#define LORA_IMMEDIATE_REQUEST_TIMEOUT 300
#define LORA_RETRY_REQUEST_TIMEOUT 1000
#define LORA_RESPONSE_TIME_TIMEOUT 5000
#define LORA_CHALET_STATUS_POWER_RELAY_MASK 0x01
#define LORA_CHALET_STATUS_CUR_SENSOR_MASK 0x02
class CChaletLoraDevice : public QObject, public CNetworkDevice class CChaletLoraDevice : public QObject, public CNetworkDevice
@ -27,6 +35,7 @@ public:
int Start(); int Start();
CChaletMainStatus GetChaletMainStatus() {return mChaletMainStatus;} CChaletMainStatus GetChaletMainStatus() {return mChaletMainStatus;}
CBlynkCloudClient mBlynkInterface;
CChaletMainStatus mChaletMainStatus; CChaletMainStatus mChaletMainStatus;
QList<CChaletNetworkMessage> mPendingNetworkMsgList; QList<CChaletNetworkMessage> mPendingNetworkMsgList;

View File

@ -11,5 +11,7 @@
#define ON_STATE 1 #define ON_STATE 1
#define OFF_STATE 0 #define OFF_STATE 0
#define UNKNOWN_STATE -1 #define UNKNOWN_STATE -1
#define OK_STATE 1
#define DEFECT_STATE 0
#endif // GLOBALDEFINE_H #endif // GLOBALDEFINE_H

View File

@ -0,0 +1,5 @@
#include "HttpServer.h"
CHttpServer::CHttpServer()
{
}

View File

@ -0,0 +1,11 @@
#ifndef HTTPSERVER_H
#define HTTPSERVER_H
class CHttpServer
{
public:
CHttpServer();
};
#endif // HTTPSERVER_H

View File

@ -1,7 +1,6 @@
#include "MasterCtrl.h" #include "MasterCtrl.h"
#include <QApplication> #include <QApplication>
// #include <QByteArray> // #include <QByteArray>
//#include <QBuffer> //#include <QBuffer>
@ -98,6 +97,7 @@ void CMasterCtrl::Start()
// mAppWidget.show(); // mAppWidget.show();

View File

@ -15,6 +15,7 @@
#include "ChaletLoraDevice.h" #include "ChaletLoraDevice.h"
//#include "ChaletLoraInterface.h" //#include "ChaletLoraInterface.h"
#include "LoraNetworkCommIF.h" #include "LoraNetworkCommIF.h"
#include "HttpServer.h"
//#include "AppIconWidget.h" //#include "AppIconWidget.h"
@ -43,6 +44,8 @@ public:
CLoraNetworkCommIF *mChaletLoraNetworkCommInterface; CLoraNetworkCommIF *mChaletLoraNetworkCommInterface;
// CAppIconWidget mAppWidget; // CAppIconWidget mAppWidget;
CHttpServer mHttpServer;