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

wirenboard / wb-mqtt-mbgate / 79

31 Jul 2026 10:42AM UTC coverage: 69.352% (-1.3%) from 70.692%
79

push

github

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

706 of 926 branches covered (76.24%)

1188 of 1713 relevant lines covered (69.35%)

11.4 hits per line

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

0.0
/src/main.cpp
1
#include <cstring>
2
#include <getopt.h>
3
#include <string>
4
#include <tuple>
5

6
#include "config_parser.h"
7
#include "log.h"
8
#include "mbgate_exception.h"
9
#include "modbus_lmb_backend.h"
10
#include "modbus_wrapper.h"
11
#include "observer.h"
12

13
#include <wblib/signal_handling.h>
14

15
/* for version message */
16
#define WBMQTT_NAME "wb-mqtt-mbgate"
17

18
#define LOG(logger) ::logger.Log() << "[mbgate] "
19

20
#define STR(x) #x
21
#define XSTR(x) STR(x)
22

23
#ifdef WBMQTT_DIRTYTREE
24
#define WBMQTT_DIRTYTREE_MSG "\033[31m\033[5mGIT TREE WAS DIRTY DURING THE BUILD!\033[0m\n"
25
#else
26
#define WBMQTT_DIRTYTREE_MSG ""
27
#endif
28

29
using namespace std;
30
using namespace WBMQTT;
31

32
const auto DRIVER_STOP_TIMEOUT_S = chrono::seconds(10);
33

34
namespace
35
{
36
    constexpr auto EXIT_NOTCONFIGURED = 6; // The program is not configured
37
    constexpr auto EXIT_NOTRUNNING = 7;    // The program is not running
38

39
    void PrintUsage()
×
40
    {
41
        cout << WBMQTT_NAME << XSTR(WBMQTT_VERSION) << " git " << XSTR(WBMQTT_COMMIT) << " build on " << __DATE__ << " "
42
             << __TIME__ << endl
×
43
             << WBMQTT_DIRTYTREE_MSG << endl
×
44
             << "Usage:" << endl
×
45
             << " " << WBMQTT_NAME << " [options]" << endl
×
46
             << "Options:" << endl
×
47
             << "  -d  level    enable debuging output:" << endl
×
48
             << "                 1 - " << WBMQTT_NAME << " only;" << endl
×
49
             << "                 2 - mqtt only;" << endl
×
50
             << "                 3 - both;" << endl
×
51
             << "                 negative values - silent mode (-1, -2, -3))" << endl
×
52
             << "  -c  config   config file (default /etc/wb-mqtt-mbgate.conf)" << endl;
×
53
    }
×
54

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

60
        while ((c = getopt(argc, argv, "d:c:")) != -1) {
×
61
            switch (c) {
×
62
                case 'd':
×
63
                    debugLevel = stoi(optarg);
×
64
                    break;
×
65
                case 'c':
×
66
                    configFile = optarg;
×
67
                    break;
×
68

69
                case '?':
×
70
                default:
71
                    PrintUsage();
×
72
                    exit(2);
×
73
            }
74
        }
75

76
        switch (debugLevel) {
×
77
            case 0:
×
78
                break;
×
79
            case -1:
×
80
                ::Info.SetEnabled(false);
×
81
                break;
×
82

83
            case -2:
×
84
                WBMQTT::Info.SetEnabled(false);
×
85
                break;
×
86

87
            case -3:
×
88
                WBMQTT::Info.SetEnabled(false);
×
89
                ::Info.SetEnabled(false);
×
90
                break;
×
91

92
            case 1:
×
93
                ::Debug.SetEnabled(true);
×
94
                break;
×
95

96
            case 2:
×
97
                WBMQTT::Debug.SetEnabled(true);
×
98
                break;
×
99

100
            case 3:
×
101
                WBMQTT::Debug.SetEnabled(true);
×
102
                ::Debug.SetEnabled(true);
×
103
                break;
×
104

105
            default:
×
106
                cout << "Invalid -d parameter value " << debugLevel << endl;
×
107
                PrintUsage();
×
108
                exit(2);
×
109
        }
110

111
        if (optind < argc) {
×
112
            for (int index = optind; index < argc; ++index) {
×
113
                cout << "Skipping unknown argument " << argv[index] << endl;
×
114
            }
115
        }
116
    }
×
117
}
118

119
class ModbusGatewayBuilder
120
{
121
public:
122
    static tuple<PModbusServer, PMqttClient> fromConfig(IConfigParser& parser)
×
123
    {
124
        PModbusServer modbus;
×
125
        PMqttClient client;
×
126

127
        tie(modbus, client) = parser.Build();
×
128

129
        modbus->AllocateCache();
×
130
        modbus->Backend()->SetDebug(parser.Debug());
×
131
        modbus->Backend()->Listen();
×
132

133
        return make_tuple(modbus, client);
×
134
    }
×
135
};
136

137
int main(int argc, char* argv[])
×
138
{
139
    string configFile("/etc/wb-mqtt-mbgate.conf");
×
140

141
    WBMQTT::SignalHandling::Handle({SIGINT, SIGTERM});
×
142
    WBMQTT::SignalHandling::OnSignals({SIGINT, SIGTERM}, [&] { WBMQTT::SignalHandling::Stop(); });
×
143
    WBMQTT::SetThreadName(WBMQTT_NAME);
×
144

145
    ParseCommadLine(argc, argv, configFile);
×
146

147
    WBMQTT::SignalHandling::SetOnTimeout(DRIVER_STOP_TIMEOUT_S, [&] {
×
148
        LOG(Error) << "Driver takes too long to stop. Exiting.";
×
149
        exit(1);
×
150
    });
151

152
    bool running = true;
×
153

154
    WBMQTT::SignalHandling::OnSignals({SIGINT, SIGTERM}, [&] { running = false; });
×
155

156
    try {
157
        PModbusServer s;
×
158
        PMqttClient t;
×
159
        TJSONConfigParser configParser(configFile, "/usr/share/wb-mqtt-confed/schemas/wb-mqtt-mbgate.schema.json");
×
160
        if (configParser.Debug())
×
161
            ::Debug.SetEnabled(true);
×
162

163
        tie(s, t) = ModbusGatewayBuilder::fromConfig(configParser);
×
164

165
        LOG(Info) << "Start loops";
×
166

167
        WBMQTT::SignalHandling::Start();
×
168

169
        t->Start();
×
170

171
        while (running) {
×
172
            if (s->Loop(1000) == -1)
×
173
                throw runtime_error("IO Error occured in server work cycle");
×
174
        }
175

176
        LOG(Info) << "Shutting down";
×
177

178
        t->Stop();
×
179
        WBMQTT::SignalHandling::Wait();
×
180
    } catch (const TEmptyConfigException&) {
×
181
        LOG(Error) << "All channels are disabled, stopping service gracefully";
×
182
        return EXIT_NOTRUNNING;
×
183
    } catch (const TConfigException& e) {
×
184
        LOG(Error) << "FATAL: " << e.what();
×
185
        return EXIT_NOTCONFIGURED;
×
186
    } catch (const exception& e) {
×
187
        LOG(Error) << "FATAL: " << e.what();
×
188
        return EXIT_FAILURE;
×
189
    }
×
190

191
    return EXIT_SUCCESS;
×
192
}
×
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