powersync-plugins-modbus/libnymea-sunspec/models/sunspeclocationmodel.cpp

253 lines
8.8 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-later
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of libnymea-sunspec.
*
* libnymea-sunspec is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* libnymea-sunspec is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libnymea-sunspec. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "sunspeclocationmodel.h"
#include "sunspecconnection.h"
SunSpecLocationModel::SunSpecLocationModel(SunSpecConnection *connection, quint16 modbusStartRegister, quint16 modelLength, SunSpecDataPoint::ByteOrder byteOrder, QObject *parent) :
SunSpecModel(connection, modbusStartRegister, 305, modelLength, byteOrder, parent)
{
m_modelBlockType = SunSpecModel::ModelBlockTypeFixed;
initDataPoints();
}
SunSpecLocationModel::~SunSpecLocationModel()
{
}
QString SunSpecLocationModel::name() const
{
return "location";
}
QString SunSpecLocationModel::description() const
{
return "Include to support location measurements";
}
QString SunSpecLocationModel::label() const
{
return "GPS";
}
QString SunSpecLocationModel::tm() const
{
return m_tm;
}
QString SunSpecLocationModel::date() const
{
return m_date;
}
QString SunSpecLocationModel::location() const
{
return m_location;
}
float SunSpecLocationModel::lat() const
{
return m_lat;
}
float SunSpecLocationModel::longitude() const
{
return m_longitude;
}
qint32 SunSpecLocationModel::altitude() const
{
return m_altitude;
}
void SunSpecLocationModel::initDataPoints()
{
SunSpecDataPoint modelIdDataPoint;
modelIdDataPoint.setName("ID");
modelIdDataPoint.setLabel("Model ID");
modelIdDataPoint.setDescription("Model identifier");
modelIdDataPoint.setMandatory(true);
modelIdDataPoint.setSize(1);
modelIdDataPoint.setAddressOffset(0);
modelIdDataPoint.setSunSpecDataType("uint16");
modelIdDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(modelIdDataPoint.name(), modelIdDataPoint);
SunSpecDataPoint modelLengthDataPoint;
modelLengthDataPoint.setName("L");
modelLengthDataPoint.setLabel("Model Length");
modelLengthDataPoint.setDescription("Model length");
modelLengthDataPoint.setMandatory(true);
modelLengthDataPoint.setSize(1);
modelLengthDataPoint.setAddressOffset(1);
modelLengthDataPoint.setSunSpecDataType("uint16");
modelLengthDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(modelLengthDataPoint.name(), modelLengthDataPoint);
SunSpecDataPoint tmDataPoint;
tmDataPoint.setName("Tm");
tmDataPoint.setLabel("Tm");
tmDataPoint.setDescription("UTC 24 hour time stamp to millisecond hhmmss.sssZ format");
tmDataPoint.setUnits("hhmmss.sssZ");
tmDataPoint.setSize(6);
tmDataPoint.setAddressOffset(2);
tmDataPoint.setBlockOffset(0);
tmDataPoint.setSunSpecDataType("string");
tmDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(tmDataPoint.name(), tmDataPoint);
SunSpecDataPoint dateDataPoint;
dateDataPoint.setName("Date");
dateDataPoint.setLabel("Date");
dateDataPoint.setDescription("UTC Date string YYYYMMDD format");
dateDataPoint.setUnits("YYYYMMDD");
dateDataPoint.setSize(4);
dateDataPoint.setAddressOffset(8);
dateDataPoint.setBlockOffset(6);
dateDataPoint.setSunSpecDataType("string");
dateDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(dateDataPoint.name(), dateDataPoint);
SunSpecDataPoint locationDataPoint;
locationDataPoint.setName("Loc");
locationDataPoint.setLabel("Location");
locationDataPoint.setDescription("Location string (40 chars max)");
locationDataPoint.setUnits("text");
locationDataPoint.setSize(20);
locationDataPoint.setAddressOffset(12);
locationDataPoint.setBlockOffset(10);
locationDataPoint.setSunSpecDataType("string");
locationDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(locationDataPoint.name(), locationDataPoint);
SunSpecDataPoint latDataPoint;
latDataPoint.setName("Lat");
latDataPoint.setLabel("Lat");
latDataPoint.setDescription("Latitude with seven degrees of precision");
latDataPoint.setUnits("Degrees");
latDataPoint.setSize(2);
latDataPoint.setAddressOffset(32);
latDataPoint.setBlockOffset(30);
latDataPoint.setScaleFactorName("-7");
latDataPoint.setSunSpecDataType("int32");
latDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(latDataPoint.name(), latDataPoint);
SunSpecDataPoint longitudeDataPoint;
longitudeDataPoint.setName("Long");
longitudeDataPoint.setLabel("Long");
longitudeDataPoint.setDescription("Longitude with seven degrees of precision");
longitudeDataPoint.setUnits("Degrees");
longitudeDataPoint.setSize(2);
longitudeDataPoint.setAddressOffset(34);
longitudeDataPoint.setBlockOffset(32);
longitudeDataPoint.setScaleFactorName("-7");
longitudeDataPoint.setSunSpecDataType("int32");
longitudeDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(longitudeDataPoint.name(), longitudeDataPoint);
SunSpecDataPoint altitudeDataPoint;
altitudeDataPoint.setName("Alt");
altitudeDataPoint.setLabel("Altitude");
altitudeDataPoint.setDescription("Altitude measurement in meters");
altitudeDataPoint.setUnits("meters");
altitudeDataPoint.setSize(2);
altitudeDataPoint.setAddressOffset(36);
altitudeDataPoint.setBlockOffset(34);
altitudeDataPoint.setSunSpecDataType("int32");
altitudeDataPoint.setByteOrder(m_byteOrder);
m_dataPoints.insert(altitudeDataPoint.name(), altitudeDataPoint);
}
void SunSpecLocationModel::processBlockData()
{
// Update properties according to the data point type
if (m_dataPoints.value("Tm").isValid())
m_tm = m_dataPoints.value("Tm").toString();
if (m_dataPoints.value("Date").isValid())
m_date = m_dataPoints.value("Date").toString();
if (m_dataPoints.value("Loc").isValid())
m_location = m_dataPoints.value("Loc").toString();
if (m_dataPoints.value("Lat").isValid())
m_lat = m_dataPoints.value("Lat").toFloatWithSSF(-7);
if (m_dataPoints.value("Long").isValid())
m_longitude = m_dataPoints.value("Long").toFloatWithSSF(-7);
if (m_dataPoints.value("Alt").isValid())
m_altitude = m_dataPoints.value("Alt").toInt32();
qCDebug(dcSunSpecModelData()) << this;
}
QDebug operator<<(QDebug debug, SunSpecLocationModel *model)
{
debug.nospace().noquote() << "SunSpecLocationModel(Model: " << model->modelId() << ", Register: " << model->modbusStartRegister() << ", Length: " << model->modelLength() << ")\n";
debug.nospace().noquote() << " - " << model->dataPoints().value("Tm") << "-->";
if (model->dataPoints().value("Tm").isValid()) {
debug.nospace().noquote() << model->tm() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Date") << "-->";
if (model->dataPoints().value("Date").isValid()) {
debug.nospace().noquote() << model->date() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Loc") << "-->";
if (model->dataPoints().value("Loc").isValid()) {
debug.nospace().noquote() << model->location() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Lat") << "-->";
if (model->dataPoints().value("Lat").isValid()) {
debug.nospace().noquote() << model->lat() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Long") << "-->";
if (model->dataPoints().value("Long").isValid()) {
debug.nospace().noquote() << model->longitude() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
debug.nospace().noquote() << " - " << model->dataPoints().value("Alt") << "-->";
if (model->dataPoints().value("Alt").isValid()) {
debug.nospace().noquote() << model->altitude() << "\n";
} else {
debug.nospace().noquote() << "NaN\n";
}
return debug.space().quote();
}