Skip to content

Commit

Permalink
Port modbus from Qt to libuv
Browse files Browse the repository at this point in the history
  • Loading branch information
mincequi committed Dec 31, 2023
1 parent b1fc141 commit bfc9d6f
Show file tree
Hide file tree
Showing 49 changed files with 453 additions and 502 deletions.
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ option(BUILD_TESTS "Build test programs" OFF)

find_package(Threads)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network SerialBus REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED)

add_subdirectory(src/cli)
add_subdirectory(src/common)
add_subdirectory(src/config)
add_subdirectory(src/fronius)
add_subdirectory(src/http)
#add_subdirectory(src/influx)
add_subdirectory(src/modbus)
add_subdirectory(src/mqtt)
Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,7 @@ sudo apt install \
git \
snapd \
libboost-dev \
libcurl4-openssl-dev \
libqt6serialbus6-bin \
qt6-serialbus-dev \
qt6-serialport-dev
qt6-base-dev
sudo snap install flutter --classic
flutter # init flutter first
Expand Down
4 changes: 2 additions & 2 deletions src/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FetchContent_Declare(clipp
URL https://github.com/muellan/clipp/archive/refs/tags/v1.2.3.tar.gz
URL https://github.com/muellan/clipp/archive/refs/tags/v1.2.3.tar.gz
)
if(NOT clipp_POPULATED)
FetchContent_Populate(clipp)
FetchContent_Populate(clipp)
endif()

add_library(cli STATIC
Expand Down
14 changes: 14 additions & 0 deletions src/common/Asio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Asio.h"

Asio* Asio::instance() {
if (!_instance) _instance = new Asio();
return _instance;
}

asio::io_context& Asio::ioc() {
return _ioc;
}

Asio::Asio() {
}

19 changes: 19 additions & 0 deletions src/common/Asio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <asio/io_context.hpp>

#define _asio Asio::instance()

class Asio {
public:
static Asio* instance();

asio::io_context& ioc();

private:
Asio();

static inline Asio* _instance = nullptr;

asio::io_context _ioc;
};
1 change: 0 additions & 1 deletion src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ PUBLIC
${CMAKE_DL_LIBS}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::SerialBus
magic_enum
rpp
rppqt
Expand Down
4 changes: 2 additions & 2 deletions src/config/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
include(FetchContent)

FetchContent_Declare(toml11
URL https://github.com/ToruNiina/toml11/archive/refs/tags/v3.7.1.tar.gz
URL https://github.com/ToruNiina/toml11/archive/refs/tags/v3.7.1.tar.gz
)
if(NOT toml11_POPULATED)
FetchContent_Populate(toml11)
FetchContent_Populate(toml11)
endif()

add_library(config
Expand Down
26 changes: 17 additions & 9 deletions src/fronius/FroniusDiscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,25 @@ using namespace sunspec;

FroniusDiscovery::FroniusDiscovery(SunSpecDiscoveryPtr sunSpecDiscovery) :
_sunSpecDiscovery(sunSpecDiscovery) {
_sunSpecDiscovery->thingDiscovered().subscribe([](ThingPtr thing) {
_sunSpecDiscovery->thingDiscovered().subscribe([this](ThingPtr thing) {
auto sunSpecThing = std::static_pointer_cast<SunSpecThing>(thing);

if ((sunSpecThing->modbusUnitId() >= 1 &&
sunSpecThing->modbusUnitId() <= 100 &&
sunSpecThing->type() == Thing::Type::SolarInverter) ||
(sunSpecThing->modbusUnitId() >= 240 &&
sunSpecThing->modbusUnitId() <= 244 &&
sunSpecThing->type() == Thing::Type::SmartMeter)) {
LOG_S(INFO) << "potential thing found> " << "id: " << sunSpecThing->sunSpecId() <<
", modbusUnitId: " << sunSpecThing->modbusUnitId();
if ((sunSpecThing->unitId() >= 1 && sunSpecThing->unitId() <= 100 &&
sunSpecThing->type() == Thing::Type::SolarInverter)) {
onSolarInverterDiscovered(sunSpecThing);
} else if ((sunSpecThing->unitId() >= 240 && sunSpecThing->unitId() <= 244 &&
sunSpecThing->type() == Thing::Type::SmartMeter)) {
onSmartMeterDiscovered(sunSpecThing);
}
});
}

void FroniusDiscovery::onSolarInverterDiscovered(SunSpecThingPtr thing) {
LOG_S(INFO) << "solar inverter found> " << "id: " << thing->sunSpecId() <<
", modbusUnitId: " << thing->unitId();
}

void FroniusDiscovery::onSmartMeterDiscovered(SunSpecThingPtr thing) {
LOG_S(INFO) << "smart meter found> " << "id: " << thing->sunSpecId() <<
", modbusUnitId: " << thing->unitId();
}
14 changes: 14 additions & 0 deletions src/fronius/FroniusDiscovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@

#include <things/sunspec/SunSpecDiscovery.h>

/**
* This will discover further Fronius SunSpec things based on a previously
* discovered SunSpec thing.
*
* A Fronius solar inverter acts as a modbus/sunspec gateway and can house
* multiple sunspec things like smart meters and further solar inverters.
* However, the SunSpecDiscovery stops polling for valid SunSpec things after
* first valid unit per host.
* This class will check for further SunSpec things on a previously discovered
* SunSpec host.
*/
class FroniusDiscovery : public ThingsDiscovery {
public:
FroniusDiscovery(SunSpecDiscoveryPtr sunSpecDiscovery);

private:
void onSolarInverterDiscovered(SunSpecThingPtr thing);
void onSmartMeterDiscovered(SunSpecThingPtr thing);

SunSpecDiscoveryPtr _sunSpecDiscovery;
};
16 changes: 0 additions & 16 deletions src/http/CMakeLists.txt

This file was deleted.

84 changes: 0 additions & 84 deletions src/http/HttpClient.cpp

This file was deleted.

29 changes: 0 additions & 29 deletions src/http/HttpClient.h

This file was deleted.

1 change: 0 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ int main(int argc, char *argv[]) {
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, []() {
uvw::loop::get_default()->run(uvw::loop::run_mode::NOWAIT);
//modbus::ModbusDiscovery::ioc.poll();
});
timer.start(100ms);

Expand Down
3 changes: 2 additions & 1 deletion src/modbus/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
add_library(modbus STATIC
ModbusDiscovery.cpp
ModbusRequest.cpp
ModbusResponse.cpp
ModbusThing.cpp
ModbusThingDecorator.cpp
)

target_link_libraries(modbus
Expand Down
23 changes: 8 additions & 15 deletions src/modbus/ModbusDiscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,15 @@

#include <common/Logger.h>
#include <config/Config.h>
#include <modbus/ModbusThing.h>
#include <things/ThingsRepository.h>

using namespace std::placeholders;
using namespace sunspec;

ModbusDiscovery::ModbusDiscovery() {
_discoveryTimer.callOnTimeout(this, &ModbusDiscovery::onStartDiscovering);
}

void ModbusDiscovery::start(int msec) {
onStartDiscovering();
_discoveryTimer.start(msec);
}

void ModbusDiscovery::stop() {
_discoveryTimer.stop();
}

void ModbusDiscovery::onStartDiscovering() {
for (const auto& c : _candidates) {
c.second.unsubscribe();
}
Expand All @@ -40,26 +29,30 @@ void ModbusDiscovery::onStartDiscovering() {
}

// Scan subnets
LOG_S(INFO) << "find things> subnet: " << subnet << "0/24";
LOG_S(1) << "find things> subnet: " << subnet << "0/24";
for (uint8_t i = 1; i < 255; ++i) {
const QString host = subnet + QString::number(i);
if (repo->thingByHost(host.toStdString())) {
continue;
}

//auto candidate = std::make_unique<SunSpecThing>(ThingInfo{ThingInfo::SunSpec, host.toStdString(), host.toStdString()});
//auto candidate = std::make_shared<ModbusThing>(ThingInfo{ThingInfo::SunSpec, host.toStdString(), host.toStdString()});
auto candidate = std::make_shared<ModbusThing>(ThingInfo{ThingInfo::SunSpec, host.toStdString(), host.toStdString()});
auto sub = candidate->stateObservable().subscribe(std::bind(&ModbusDiscovery::onCandidateStateChanged, this, candidate, _1));
candidate->connect();
_candidates.push_back({std::move(candidate), sub});
}
}

void ModbusDiscovery::onCandidateStateChanged(const ModbusThingPtr& candidate_, Thing::State state) {
void ModbusDiscovery::stop() {
}

void ModbusDiscovery::onCandidateStateChanged(const ModbusThingPtr_asio& candidate_, Thing::State state) {
assert(!_candidates.empty());
auto it = std::find_if(_candidates.begin(), _candidates.end(), [&](const auto& c) {
return c.first == candidate_;
});
if (it == _candidates.end()) return;
assert(it != _candidates.end());

// Steal candidate from container
auto candidate = std::move(*it);
Expand Down
Loading

0 comments on commit bfc9d6f

Please sign in to comment.