• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wirenboard / wb-mqtt-iec104 / 38

31 Jul 2026 10:43AM UTC coverage: 52.549% (-0.2%) from 52.705%
38

push

github

web-flow
Use exported vars instead of MAKEFLAGS for coverage options (#30)

236 of 389 branches covered (60.67%)

402 of 765 relevant lines covered (52.55%)

3.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main.cpp
1
#include <getopt.h>
2

3
#include <wblib/signal_handling.h>
4
#include <wblib/wbmqtt.h>
5

6
#include "config_parser.h"
7
#include "iec104_exception.h"
8
#include "log.h"
9

10
#define LOG(logger) ::logger.Log() << "[main] "
11

12
#define STR(x) #x
13
#define XSTR(x) STR(x)
14

15
using namespace std;
16
using namespace WBMQTT;
17

18
const auto APP_NAME = "wb-mqtt-iec104";
19
const auto CONFIG_FULL_FILE_PATH = "/etc/wb-mqtt-iec104.conf";
20
const auto CONFIG_JSON_SCHEMA_FULL_FILE_PATH = "/usr/share/wb-mqtt-confed/schemas/wb-mqtt-iec104.schema.json";
21

22
const auto DRIVER_STOP_TIMEOUT_S = chrono::seconds(10);
23

24
//! Maximun time to start application. Exceded timeout will case application termination.
25
const auto DRIVER_INIT_TIMEOUT_S = chrono::seconds(60);
26

27
const auto EXIT_NOTCONFIGURED = 6; // Error in config file; do not auto-restart by systemd, treat as failure
28
const auto EXIT_NOTRUNNING = 7;    // Nothing for service to do; do not auto-restart by systemd, do not treat as failure
29

30
namespace
31
{
32

33
    void PrintStartupInfo()
×
34
    {
35
        cout << APP_NAME << " " << XSTR(WBMQTT_VERSION) << " git " << XSTR(WBMQTT_COMMIT) << " build on " << __DATE__
36
             << " " << __TIME__ << endl;
×
37
    }
×
38

39
    void PrintUsage()
×
40
    {
41
        PrintStartupInfo();
×
42
        cout << "Usage:" << endl
×
43
             << " " << APP_NAME << " [options]" << endl
×
44
             << "Options:" << endl
×
45
             << "  -d  level    enable debugging output:" << endl
×
46
             << "                 1 - " << APP_NAME << " only;" << endl
×
47
             << "                 2 - MQTT only;" << endl
×
48
             << "                 3 - both;" << endl
×
49
             << "                 negative values - silent mode (-1, -2, -3))" << endl
×
50
             << "  -c  config   config file (default /etc/wb-mqtt-iec104.conf)" << endl
×
51
             << "  -g  config   update config file with information about active MQTT publications" << endl;
×
52
    }
×
53

54
    void ParseCommandLine(int argc, char* argv[], string& configFile)
×
55
    {
56
        int debugLevel = 0;
×
57
        int c;
58

59
        while ((c = getopt(argc, argv, "d:c:g:")) != -1) {
×
60
            switch (c) {
×
61
                case 'd':
×
62
                    debugLevel = stoi(optarg);
×
63
                    break;
×
64
                case 'c':
×
65
                    configFile = optarg;
×
66
                    break;
×
67
                case 'g':
×
68
                    try {
69
                        UpdateConfig(optarg, CONFIG_JSON_SCHEMA_FULL_FILE_PATH);
×
70
                    } catch (const exception& e) {
×
71
                        std::cerr << "FATAL: " << e.what();
×
72
                        exit(1);
×
73
                    }
×
74
                    exit(0);
×
75
                default:
×
76
                    PrintUsage();
×
77
                    exit(2);
×
78
            }
79
        }
80

81
        switch (debugLevel) {
×
82
            case 0:
×
83
                break;
×
84
            case -1:
×
85
                ::Info.SetEnabled(false);
×
86
                break;
×
87
            case -2:
×
88
                WBMQTT::Info.SetEnabled(false);
×
89
                break;
×
90
            case -3:
×
91
                WBMQTT::Info.SetEnabled(false);
×
92
                ::Info.SetEnabled(false);
×
93
                break;
×
94
            case 1:
×
95
                ::Debug.SetEnabled(true);
×
96
                break;
×
97
            case 2:
×
98
                WBMQTT::Debug.SetEnabled(true);
×
99
                break;
×
100
            case 3:
×
101
                WBMQTT::Debug.SetEnabled(true);
×
102
                ::Debug.SetEnabled(true);
×
103
                break;
×
104
            default:
×
105
                cout << "Invalid -d parameter value " << debugLevel << endl;
×
106
                PrintUsage();
×
107
                exit(2);
×
108
        }
109
    }
×
110
}
111

112
int main(int argc, char* argv[])
×
113
{
114
    string configFile(CONFIG_FULL_FILE_PATH);
×
115

116
    TPromise<void> initialized;
×
117
    SignalHandling::Handle({SIGINT, SIGTERM});
×
118
    SignalHandling::OnSignals({SIGINT, SIGTERM}, [&] { SignalHandling::Stop(); });
×
119
    SetThreadName(APP_NAME);
×
120

121
    ParseCommandLine(argc, argv, configFile);
×
122

123
    PrintStartupInfo();
×
124

125
    SignalHandling::SetWaitFor(DRIVER_INIT_TIMEOUT_S, initialized.GetFuture(), [&] {
×
126
        LOG(Error) << "Driver takes too long to initialize. Exiting.";
×
127
        exit(1);
×
128
    });
129

130
    SignalHandling::SetOnTimeout(DRIVER_STOP_TIMEOUT_S, [&] {
×
131
        LOG(Error) << "Driver takes too long to stop. Exiting.";
×
132
        exit(1);
×
133
    });
134

135
    try {
136
        TConfig config(LoadConfig(configFile, CONFIG_JSON_SCHEMA_FULL_FILE_PATH));
×
137
        config.Mqtt.Id = APP_NAME;
×
138
        if (config.Debug) {
×
139
            ::Debug.SetEnabled(true);
×
140
        }
141

142
        SignalHandling::Start();
×
143

144
        auto mqtt = NewMosquittoMqttClient(config.Mqtt);
×
145
        auto backend = NewDriverBackend(mqtt);
×
146
        auto driver = NewDriver(TDriverArgs{}.SetId(APP_NAME).SetBackend(backend));
×
147

148
        driver->StartLoop();
×
149
        driver->WaitForReady();
×
150

151
        auto IecServer(IEC104::MakeServer(config.Iec));
×
152

153
        TGateway gateway(driver, IecServer.get(), config.Devices);
×
154

155
        SignalHandling::OnSignals({SIGINT, SIGTERM}, [&] { gateway.Stop(); });
×
156

157
        initialized.Complete();
×
158
        SignalHandling::Wait();
×
159

160
    } catch (const TEmptyConfigException& e) {
×
161
        LOG(Error) << "All groups are disabled in config file, stopping service gracefully";
×
162
        return EXIT_NOTRUNNING;
×
163
    } catch (const TConfigException& e) {
×
164
        LOG(Error) << "FATAL: " << e.what();
×
165
        return EXIT_NOTCONFIGURED;
×
166
    } catch (const exception& e) {
×
167
        LOG(Error) << "FATAL: " << e.what();
×
168
        return 1;
×
169
    }
×
170

171
    return 0;
×
172
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc