├── .github ├── FUNDING.yml └── workflows │ ├── c-cpp.yml │ └── label.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── debian ├── changelog ├── compat ├── control ├── gbp.conf ├── rules └── source │ └── options ├── ledindicator.cpp ├── ledindicator.h ├── libqmqtt ├── CMakeLists.txt ├── Makefile.qmqtt ├── qmqtt.h ├── qmqtt.pri ├── qmqtt.pro ├── qmqtt_client.cpp ├── qmqtt_client.h ├── qmqtt_client_p.cpp ├── qmqtt_client_p.h ├── qmqtt_frame.cpp ├── qmqtt_frame.h ├── qmqtt_global.h ├── qmqtt_message.cpp ├── qmqtt_message.h ├── qmqtt_message_p.cpp ├── qmqtt_message_p.h ├── qmqtt_network.cpp ├── qmqtt_network.h ├── qmqtt_networkinterface.h ├── qmqtt_routedmessage.cpp ├── qmqtt_routedmessage.h ├── qmqtt_router.cpp ├── qmqtt_router.h ├── qmqtt_routesubscription.cpp ├── qmqtt_routesubscription.h ├── qmqtt_socket.cpp ├── qmqtt_socket.h ├── qmqtt_socketinterface.h ├── qmqtt_ssl_network.cpp ├── qmqtt_ssl_network.h ├── qmqtt_ssl_socket.cpp ├── qmqtt_ssl_socket.h ├── qmqtt_timer.cpp ├── qmqtt_timer.h └── qmqtt_timerinterface.h ├── main.cpp ├── main.pro ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── qcustomplot.cpp ├── qcustomplot.h ├── qmqtt-plot.desktop ├── qmqtt-plot.png ├── qmqtt-plot.svg └── res.qrc /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: 'http://koppi.github.io/' 2 | -------------------------------------------------------------------------------- /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: packages 17 | run: | 18 | sudo apt -y install debhelper pkgconf automake libtool cmake qt5-default qt5-qmake qtbase5-dev qttools5-dev-tools lsb-release 19 | - name: libraries 20 | run: | 21 | cd libqmqtt 22 | qmake 23 | make -j$(nproc) 24 | sudo make install 25 | - name: build 26 | run: | 27 | qmake 28 | make 29 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | # This workflow will triage pull requests and apply a label based on the 2 | # paths that are modified in the pull request. 3 | # 4 | # To use this workflow, you will need to set up a .github/labeler.yml 5 | # file with configuration. For more information, see: 6 | # https://github.com/actions/labeler 7 | 8 | name: Labeler 9 | on: [pull_request] 10 | 11 | jobs: 12 | label: 13 | 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: read 17 | pull-requests: write 18 | 19 | steps: 20 | - uses: actions/labeler@v2 21 | with: 22 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | qmqtt-plot 2 | main.pro.user 3 | debian/*.log 4 | qrc_res.cpp 5 | build-stamp 6 | Makefile 7 | ui_*.h 8 | moc_*.cpp 9 | *.o 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | script: 7 | - export TRAVIS_DEBIAN_DISTRIBUTION=sid; wget -O- http://travis.debian.net/script.sh | sh - 8 | 9 | branches: 10 | except: 11 | - /^debian\/\d/ 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### A Qt5 app that plots timestamped MQTT data [![C/C++ CI](https://github.com/koppi/qmqtt-plot/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/koppi/qmqtt-plot/actions/workflows/c-cpp.yml) 2 | 3 | ![qmqtt-plot screenshot](qmqtt-plot.png) 4 | 5 | * Quick Video demos: 6 | 7 | * [MQTT broker latency test with Machinekit + EtherCAT on Raspberry Pi3 ](https://www.youtube.com/watch?v=uFbr7xBjItE) 8 | * [Trajectory generation inside the Mitsubishi RM-501 Movemaster II Robot Simulator](https://www.youtube.com/watch?v=dLeDPIRKhOw) 9 | 10 | #### Build and install qmqtt-plot 11 | 12 | ```bash 13 | gh repo clone koppi/qmqtt-plot 14 | cd qmqtt-plot 15 | cd libqmqtt 16 | qmake 17 | make -j$(nproc) 18 | sudo make install 19 | cd .. 20 | qmake 21 | make 22 | ./qmqtt-plot 23 | ``` 24 | 25 | * Enter your MQTT broker's hostname and click connect. 26 | 27 | #### Credits 28 | 29 | Libraries included: 30 | 31 | * [qcustomplot.com](http://qcustomplot.com) 32 | * [qmqtt](https://github.com/emqtt/qmqtt) 33 | 34 | Artwork: 35 | 36 | * [qmqtt-plot.svg](https://openclipart.org/detail/200755/primary-plot) by danny 37 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | qmqtt-plot (0.0.1-1) UNRELEASED; urgency=medium 2 | 3 | * Bump version 0.0.1. 4 | 5 | -- Jakob Flierl Sun, 05 Jun 2016 12:46:03 +0200 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: qmqtt-plot 2 | Section: graphics 3 | Priority: optional 4 | Maintainer: Jakob Flierl 5 | Uploaders: Jakob Flierl 6 | Build-Depends: debhelper (>= 7.0.50~), pkgconf, automake, libtool, cmake, qt5-default, qt5-qmake, qtbase5-dev, qttools5-dev-tools, lsb-release 7 | Standards-Version: 3.9.7 8 | Homepage: https://github.com/koppi/qmqtt-plot 9 | Vcs-Git: git://github.com/koppi/qmqtt-plot.git 10 | Vcs-Browser: https://github.com/koppi/qmqtt-plot 11 | 12 | Package: qmqtt-plot 13 | Architecture: any 14 | Depends: ${shlibs:Depends}, ${misc:Depends} 15 | Description: MQTT plot Qt5 app 16 | A GUI that plots timestamped MQTT data. 17 | -------------------------------------------------------------------------------- /debian/gbp.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | # the default branch for upstream sources: 3 | upstream-branch = master 4 | # the default branch for the debian patch: 5 | debian-branch = master 6 | # the default tag formats used: 7 | upstream-tag = %(version)s 8 | debian-tag = debian/%(version)s 9 | # use pristine-tar: 10 | #pristine-tar = True 11 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # Uncomment this to turn on verbose mode. 4 | export DH_VERBOSE=1 5 | 6 | CXXFLAGS = -Wall -g 7 | 8 | ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) 9 | CXXFLAGS += -O0 10 | else 11 | CXXFLAGS += -O2 12 | endif 13 | ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) 14 | INSTALL_PROGRAM += -s 15 | endif 16 | 17 | QMAKE_AFTER = -after \ 18 | 'QMAKE_CXXFLAGS_RELEASE = $(CXXFLAGS)' \ 19 | 'QMAKE_POST_LINK ~= s/strip/:' 20 | 21 | build: build-stamp 22 | build-stamp: $(QUILT_STAMPFN) 23 | dh_testdir 24 | 25 | qmake $(QMAKE_AFTER) main.pro && $(MAKE) -j$(nproc) 26 | 27 | touch $@ 28 | 29 | clean: 30 | dh_testdir 31 | dh_testroot 32 | rm -f build-stamp 33 | [ ! -f Makefile ] || $(MAKE) clean 34 | dh_clean 35 | 36 | install: build 37 | dh_testdir 38 | dh_testroot 39 | dh_clean -k 40 | dh_installdirs 41 | 42 | $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/qmqtt-plot install 43 | install -d -v -m 0755 $(CURDIR)/debian/qmqtt-plot/usr/share/applications 44 | chmod 664 $(CURDIR)/debian/qmqtt-plot/usr/share/applications/qmqtt-plot.desktop 45 | 46 | install -d -v -m 0755 $(CURDIR)/debian/qmqtt-plot/usr/share/icons/hicolor/scalable/apps 47 | chmod 664 $(CURDIR)/debian/qmqtt-plot/usr/share/icons/hicolor/scalable/apps/qmqtt-plot.svg 48 | 49 | install -d -v -m 0755 $(CURDIR)/debian/qmqtt-plot/usr/bin 50 | install -m 755 -p qmqtt-plot $(CURDIR)/debian/qmqtt-plot/usr/bin/qmqtt-plot 51 | 52 | # Build architecture-independent files here. 53 | binary-indep: build install 54 | dh_testdir 55 | dh_testroot 56 | # dh_installchangelogs ChangeLog 57 | dh_installdocs -i 58 | dh_install -i 59 | dh_installman -i 60 | dh_compress -i --exclude=.cpp --exclude=.pri 61 | dh_fixperms 62 | dh_installdeb 63 | dh_gencontrol 64 | dh_md5sums 65 | dh_builddeb 66 | 67 | # Build architecture-dependent files here. 68 | binary-arch: build install 69 | dh_testdir 70 | dh_testroot 71 | # dh_installchangelogs ChangeLog 72 | dh_installdocs -s README.md 73 | dh_install -s --sourcedir=$(CURDIR)/debian/qmqtt-plot 74 | # dh_installman qmqtt-plot.1 75 | dh_installmime 76 | dh_installmenu 77 | dh_link 78 | dh_strip 79 | dh_compress -s 80 | dh_fixperms 81 | dh_makeshlibs 82 | dh_installdeb 83 | dh_shlibdeps 84 | dh_gencontrol 85 | dh_md5sums 86 | dh_builddeb 87 | 88 | binary: binary-indep binary-arch 89 | .PHONY: build clean binary-indep binary-arch binary install configure 90 | -------------------------------------------------------------------------------- /debian/source/options: -------------------------------------------------------------------------------- 1 | extend-diff-ignore = "^\.travis\.yml$" 2 | -------------------------------------------------------------------------------- /ledindicator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Jakob Flierl 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of mqttc nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #include 32 | 33 | #include "ledindicator.h" 34 | 35 | QLedIndicator::QLedIndicator(QWidget *parent) : QWidget(parent) 36 | { 37 | setDisconnected(true); 38 | scaledSize = 1000; 39 | 40 | setMinimumSize(24, 24); 41 | setOn(true); 42 | disconnectedColor1 = QColor(50,50,50); 43 | disconnectedColor2 = QColor(30,30,30); 44 | onColor1 = QColor(0,255,0); 45 | onColor2 = QColor(0,192,0); 46 | offColor1 = QColor(0,28,0); 47 | offColor2 = QColor(0,128,0); 48 | } 49 | 50 | void QLedIndicator::resizeEvent(QResizeEvent *event) { 51 | Q_UNUSED(event) 52 | update(); 53 | } 54 | 55 | void QLedIndicator::paintEvent(QPaintEvent *event) { 56 | Q_UNUSED(event) 57 | qreal realSize = qMin(width(), height()); 58 | 59 | QRadialGradient gradient; 60 | QPainter painter(this); 61 | QPen pen(Qt::black); 62 | pen.setWidth(1); 63 | 64 | // painter.setRenderHint(QPainter::Antialiasing); 65 | painter.translate((width())/2, (height())/2); 66 | painter.scale(realSize/scaledSize, realSize/scaledSize); 67 | 68 | gradient = QRadialGradient (QPointF(-500,-500), 1500, QPointF(-500,-500)); 69 | gradient.setColorAt(0, QColor(224,224,224)); 70 | gradient.setColorAt(1, QColor(28,28,28)); 71 | painter.setPen(pen); 72 | painter.setBrush(QBrush(gradient)); 73 | painter.drawEllipse(QPointF(2,2), 500-2, 500-2); 74 | 75 | gradient = QRadialGradient (QPointF(500,500), 1500, QPointF(500,500)); 76 | gradient.setColorAt(0, QColor(224,224,224)); 77 | gradient.setColorAt(1, QColor(28,28,28)); 78 | painter.setPen(pen); 79 | painter.setBrush(QBrush(gradient)); 80 | painter.drawEllipse(QPointF(2,2), 450-2, 450-2); 81 | 82 | painter.setPen(pen); 83 | 84 | if (isDisconnected()) { 85 | gradient = QRadialGradient (QPointF(500,500), 1500, QPointF(500,500)); 86 | gradient.setColorAt(0, disconnectedColor1); 87 | gradient.setColorAt(1, disconnectedColor2); 88 | } else { 89 | if (isOn()) { 90 | gradient = QRadialGradient (QPointF(-500,-500), 1500, QPointF(-500,-500)); 91 | gradient.setColorAt(0, onColor1); 92 | gradient.setColorAt(1, onColor2); 93 | } else { 94 | gradient = QRadialGradient (QPointF(500,500), 1500, QPointF(500,500)); 95 | gradient.setColorAt(0, offColor1); 96 | gradient.setColorAt(1, offColor2); 97 | } 98 | } 99 | painter.setBrush(gradient); 100 | painter.drawEllipse(QPointF(2,2), 400-2, 400-2); 101 | } 102 | -------------------------------------------------------------------------------- /ledindicator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Jakob Flierl 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of mqttc nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #ifndef QLEDINDICATOR_H 32 | #define QLEDINDICATOR_H 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | class QLedIndicator : public QWidget 39 | { 40 | Q_PROPERTY(QColor disconnectedColor1 WRITE setDisconnectedColor1 READ getDisconnectedColor1 ); 41 | Q_PROPERTY(QColor disconnectedColor2 WRITE setDisconnectedColor2 READ getDisconnectedColor2 ); 42 | Q_PROPERTY(QColor onColor1 WRITE setOnColor1 READ getOnColor1 ); 43 | Q_PROPERTY(QColor onColor2 WRITE setOnColor2 READ getOnColor2 ); 44 | Q_PROPERTY(QColor offColor1 WRITE setOffColor1 READ getOffColor1 ); 45 | Q_PROPERTY(QColor offColor2 WRITE setOffColor2 READ getOffColor2 ); 46 | Q_PROPERTY(bool disconnected WRITE setDisconnected READ isDisconnected ); 47 | 48 | Q_OBJECT 49 | public: 50 | QLedIndicator(QWidget *parent); 51 | 52 | void setDisconnected(bool c) { disconnected = c; update(); } 53 | void setDisconnectedColor1(QColor c) { disconnectedColor1 = c; update(); } 54 | void setDisconnectedColor2(QColor c) { disconnectedColor2 = c; update(); } 55 | void setOnColor1(QColor c) { onColor1 = c; update(); } 56 | void setOffColor1(QColor c) { offColor1 = c; update(); } 57 | void setOnColor2(QColor c) { onColor2 = c; update(); } 58 | void setOffColor2(QColor c) { offColor2 = c; update(); } 59 | 60 | void setOn(bool onoff) { on = onoff; } 61 | 62 | bool isDisconnected(void) { return disconnected; } 63 | QColor getDisconnectedColor1(void) { return disconnectedColor1; } 64 | QColor getDisconnectedColor2(void) { return disconnectedColor2; } 65 | QColor getOnColor1(void) { return onColor1; } 66 | QColor getOffColor1(void) { return offColor1; } 67 | QColor getOnColor2(void) { return onColor2; } 68 | QColor getOffColor2(void) { return offColor2; } 69 | 70 | bool isOn() { return on; } 71 | 72 | protected: 73 | virtual void paintEvent (QPaintEvent *event); 74 | virtual void resizeEvent(QResizeEvent *event); 75 | 76 | private: 77 | qreal scaledSize; 78 | QColor disconnectedColor1, disconnectedColor2; 79 | QColor onColor1, offColor1; 80 | QColor onColor2, offColor2; 81 | QPixmap ledBuffer; 82 | bool disconnected; 83 | bool on; 84 | }; 85 | 86 | #endif // QLEDINDICATOR_H 87 | -------------------------------------------------------------------------------- /libqmqtt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.11) 2 | 3 | project(qmqtt) 4 | 5 | set(CMAKE_VERBOSE_MAKEFILE on) 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | set(CMAKE_AUTOMOC ON) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 9 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 10 | set(CMAKE_CXX_FLAGS_RELEASE "-O0 -g0") 11 | set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") 12 | set(CMAKE_C_FLAGS_RELEASE "-O0 -g0") 13 | set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") 14 | 15 | find_package(Qt5Core REQUIRED) 16 | find_package(Qt5Network REQUIRED) 17 | 18 | file(GLOB srcfiles "*.cpp") 19 | file(GLOB headerfiles "*.h") 20 | 21 | add_library(qmqtt SHARED ${srcfiles} ${headerfiles}) 22 | target_link_libraries(qmqtt Qt5::Core Qt5::Network) 23 | 24 | install(TARGETS qmqtt DESTINATION "lib") 25 | install(FILES ${headerfiles} DESTINATION "include") 26 | 27 | add_subdirectory(examples) 28 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt.h - qmqtt library heaer 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_H 33 | #define QMQTT_H 34 | 35 | #include "qmqtt_message.h" 36 | #include "qmqtt_client.h" 37 | 38 | #endif // QMQTT_H 39 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | 4 | HEADERS += \ 5 | $$PWD/qmqtt_client_p.h \ 6 | $$PWD/qmqtt_client.h \ 7 | $$PWD/qmqtt_frame.h \ 8 | $$PWD/qmqtt_global.h \ 9 | $$PWD/qmqtt_message.h \ 10 | $$PWD/qmqtt_network.h \ 11 | $$PWD/qmqtt_ssl_network.h \ 12 | $$PWD/qmqtt.h \ 13 | $$PWD/qmqtt_routesubscription.h \ 14 | $$PWD/qmqtt_routedmessage.h \ 15 | $$PWD/qmqtt_router.h \ 16 | $$PWD/qmqtt_networkinterface.h \ 17 | $$PWD/qmqtt_message_p.h \ 18 | $$PWD/qmqtt_socket.h \ 19 | $$PWD/qmqtt_ssl_socket.h \ 20 | $$PWD/qmqtt_socketinterface.h \ 21 | $$PWD/qmqtt_timerinterface.h \ 22 | $$PWD/qmqtt_timer.h 23 | 24 | SOURCES += \ 25 | $$PWD/qmqtt_client_p.cpp \ 26 | $$PWD/qmqtt_client.cpp \ 27 | $$PWD/qmqtt_frame.cpp \ 28 | $$PWD/qmqtt_message.cpp \ 29 | $$PWD/qmqtt_network.cpp \ 30 | $$PWD/qmqtt_ssl_network.cpp \ 31 | $$PWD/qmqtt_routesubscription.cpp \ 32 | $$PWD/qmqtt_routedmessage.cpp \ 33 | $$PWD/qmqtt_router.cpp \ 34 | $$PWD/qmqtt_message_p.cpp \ 35 | $$PWD/qmqtt_socket.cpp \ 36 | $$PWD/qmqtt_ssl_socket.cpp \ 37 | $$PWD/qmqtt_timer.cpp 38 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt.pro: -------------------------------------------------------------------------------- 1 | QT += network 2 | 3 | QT -= gui 4 | 5 | TARGET = qmqtt 6 | TEMPLATE = lib 7 | 8 | DEFINES += QMQTT_LIBRARY 9 | 10 | SOURCES += qmqtt_client.cpp \ 11 | qmqtt_network.cpp \ 12 | qmqtt_frame.cpp \ 13 | qmqtt_client_p.cpp \ 14 | qmqtt_message.cpp \ 15 | qmqtt_router.cpp \ 16 | qmqtt_routesubscription.cpp \ 17 | qmqtt_routedmessage.cpp \ 18 | qmqtt_message_p.cpp \ 19 | qmqtt_socket.cpp \ 20 | qmqtt_timer.cpp \ 21 | qmqtt_ssl_socket.cpp \ 22 | qmqtt_ssl_network.cpp 23 | 24 | HEADERS += qmqtt_client.h\ 25 | qmqtt_global.h \ 26 | qmqtt_network.h \ 27 | qmqtt_frame.h \ 28 | qmqtt_client_p.h \ 29 | qmqtt_message.h \ 30 | qmqtt_router.h \ 31 | qmqtt.h \ 32 | qmqtt_routesubscription.h \ 33 | qmqtt_routedmessage.h \ 34 | qmqtt_networkinterface.h \ 35 | qmqtt_message_p.h \ 36 | qmqtt_socketinterface.h \ 37 | qmqtt_socket.h \ 38 | qmqtt_timer.h \ 39 | qmqtt_timerinterface.h \ 40 | qmqtt_ssl_socket.h \ 41 | qmqtt_ssl_network.h 42 | 43 | isEmpty(PREFIX) { 44 | contains(MEEGO_EDITION,harmattan) { 45 | PREFIX = /usr 46 | } else:unix:!symbian { 47 | maemo5 { 48 | PREFIX = /opt/usr 49 | } else { 50 | PREFIX = /usr/local 51 | } 52 | } else { 53 | PREFIX = $$[QT_INSTALL_PREFIX] 54 | } 55 | } 56 | 57 | headers.files = $$HEADERS 58 | headers.path = $$PREFIX/include/qmqtt 59 | target.path = $$PREFIX/lib 60 | INSTALLS += headers target 61 | 62 | OTHER_FILES += \ 63 | qmqtt.pri 64 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_client.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_client.cpp - qmqtt client 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #include "qmqtt_client.h" 34 | #include "qmqtt_client_p.h" 35 | 36 | QMQTT::Client::Client(const QHostAddress& host, 37 | const quint16 port, 38 | QObject* parent) 39 | : QObject(parent) 40 | , d_ptr(new ClientPrivate(this)) 41 | { 42 | Q_D(Client); 43 | d->init(host, port); 44 | } 45 | 46 | QMQTT::Client::Client(const QString &hostName, 47 | const quint16 port, 48 | const bool ssl, 49 | const bool ignoreSelfSigned, 50 | QObject* parent) 51 | : QObject(parent) 52 | , d_ptr(new ClientPrivate(this)) 53 | { 54 | Q_D(Client); 55 | d->init(hostName, port, ssl, ignoreSelfSigned); 56 | } 57 | 58 | QMQTT::Client::Client(NetworkInterface* network, 59 | const QHostAddress& host, 60 | const quint16 port, 61 | QObject* parent) 62 | : QObject(parent) 63 | , d_ptr(new ClientPrivate(this)) 64 | { 65 | Q_D(Client); 66 | d->init(host, port, network); 67 | } 68 | 69 | QMQTT::Client::~Client() 70 | { 71 | } 72 | 73 | QHostAddress QMQTT::Client::host() const 74 | { 75 | Q_D(const Client); 76 | return d->host(); 77 | } 78 | 79 | void QMQTT::Client::setHost(const QHostAddress& host) 80 | { 81 | Q_D(Client); 82 | d->setHost(host); 83 | } 84 | 85 | QString QMQTT::Client::hostName() const 86 | { 87 | Q_D(const Client); 88 | return d->hostName(); 89 | } 90 | 91 | void QMQTT::Client::setHostName(const QString &hostName) 92 | { 93 | Q_D(Client); 94 | d->setHostName(hostName); 95 | } 96 | 97 | quint16 QMQTT::Client::port() const 98 | { 99 | Q_D(const Client); 100 | return d->port(); 101 | } 102 | 103 | void QMQTT::Client::setPort(const quint16 port) 104 | { 105 | Q_D(Client); 106 | d->setPort(port); 107 | } 108 | 109 | QString QMQTT::Client::clientId() const 110 | { 111 | Q_D(const Client); 112 | return d->clientId(); 113 | } 114 | 115 | void QMQTT::Client::setClientId(const QString& clientId) 116 | { 117 | Q_D(Client); 118 | d->setClientId(clientId); 119 | } 120 | 121 | QString QMQTT::Client::username() const 122 | { 123 | Q_D(const Client); 124 | return d->username(); 125 | } 126 | 127 | void QMQTT::Client::setUsername(const QString& username) 128 | { 129 | Q_D(Client); 130 | d->setUsername(username); 131 | } 132 | 133 | QString QMQTT::Client::password() const 134 | { 135 | Q_D(const Client); 136 | return d->password(); 137 | } 138 | 139 | void QMQTT::Client::setPassword(const QString& password) 140 | { 141 | Q_D(Client); 142 | d->setPassword(password); 143 | } 144 | 145 | quint16 QMQTT::Client::keepAlive() const 146 | { 147 | Q_D(const Client); 148 | return d->keepAlive(); 149 | } 150 | 151 | void QMQTT::Client::setKeepAlive(const quint16 keepAlive) 152 | { 153 | Q_D(Client); 154 | d->setKeepAlive(keepAlive); 155 | } 156 | 157 | bool QMQTT::Client::cleanSession() const 158 | { 159 | Q_D(const Client); 160 | return d->cleanSession(); 161 | } 162 | 163 | void QMQTT::Client::setCleanSession(const bool cleanSession) 164 | { 165 | Q_D(Client); 166 | d->setCleanSession(cleanSession); 167 | } 168 | 169 | bool QMQTT::Client::autoReconnect() const 170 | { 171 | Q_D(const Client); 172 | return d->autoReconnect(); 173 | } 174 | 175 | void QMQTT::Client::setAutoReconnect(const bool value) 176 | { 177 | Q_D(Client); 178 | d->setAutoReconnect(value); 179 | } 180 | 181 | int QMQTT::Client::autoReconnectInterval() const 182 | { 183 | Q_D(const Client); 184 | return d->autoReconnectInterval(); 185 | } 186 | 187 | void QMQTT::Client::setAutoReconnectInterval(const int autoReconnectInterval) 188 | { 189 | Q_D(Client); 190 | d->setAutoReconnectInterval(autoReconnectInterval); 191 | } 192 | 193 | QString QMQTT::Client::willTopic() const 194 | { 195 | Q_D(const Client); 196 | return d->willTopic(); 197 | } 198 | 199 | void QMQTT::Client::setWillTopic(const QString& willTopic) 200 | { 201 | Q_D(Client); 202 | d->setWillTopic(willTopic); 203 | } 204 | 205 | quint8 QMQTT::Client::willQos() const 206 | { 207 | Q_D(const Client); 208 | return d->willQos(); 209 | } 210 | 211 | void QMQTT::Client::setWillQos(const quint8 willQos) 212 | { 213 | Q_D(Client); 214 | d->setWillQos(willQos); 215 | } 216 | 217 | bool QMQTT::Client::willRetain() const 218 | { 219 | Q_D(const Client); 220 | return d->willRetain(); 221 | } 222 | 223 | void QMQTT::Client::setWillRetain(const bool willRetain) 224 | { 225 | Q_D(Client); 226 | d->setWillRetain(willRetain); 227 | } 228 | 229 | QString QMQTT::Client::willMessage() const 230 | { 231 | Q_D(const Client); 232 | return d->willMessage(); 233 | } 234 | 235 | void QMQTT::Client::setWillMessage(const QString& willMessage) 236 | { 237 | Q_D(Client); 238 | d->setWillMessage(willMessage); 239 | } 240 | 241 | QMQTT::ConnectionState QMQTT::Client::connectionState() const 242 | { 243 | Q_D(const Client); 244 | return d->connectionState(); 245 | } 246 | 247 | bool QMQTT::Client::isConnectedToHost() const 248 | { 249 | Q_D(const Client); 250 | return d->isConnectedToHost(); 251 | } 252 | 253 | void QMQTT::Client::connectToHost() 254 | { 255 | Q_D(Client); 256 | d->connectToHost(); 257 | } 258 | 259 | void QMQTT::Client::onNetworkConnected() 260 | { 261 | Q_D(Client); 262 | d->onNetworkConnected(); 263 | } 264 | 265 | quint16 QMQTT::Client::publish(const Message& message) 266 | { 267 | Q_D(Client); 268 | return d->publish(message); 269 | } 270 | 271 | quint16 QMQTT::Client::subscribe(const QString& topic, const quint8 qos) 272 | { 273 | Q_D(Client); 274 | return d->subscribe(topic, qos); 275 | } 276 | 277 | void QMQTT::Client::unsubscribe(const QString& topic) 278 | { 279 | Q_D(Client); 280 | d->unsubscribe(topic); 281 | } 282 | 283 | void QMQTT::Client::onTimerPingReq() 284 | { 285 | Q_D(Client); 286 | d->onTimerPingReq(); 287 | } 288 | 289 | void QMQTT::Client::disconnectFromHost() 290 | { 291 | Q_D(Client); 292 | d->disconnectFromHost(); 293 | } 294 | 295 | void QMQTT::Client::onNetworkReceived(const QMQTT::Frame& frame) 296 | { 297 | Q_D(Client); 298 | d->onNetworkReceived(frame); 299 | } 300 | 301 | void QMQTT::Client::onNetworkDisconnected() 302 | { 303 | Q_D(Client); 304 | d->onNetworkDisconnected(); 305 | } 306 | 307 | void QMQTT::Client::onNetworkError(QAbstractSocket::SocketError error) 308 | { 309 | Q_D(Client); 310 | d->onNetworkError(error); 311 | } 312 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_client.h - qmqtt client header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_CLIENT_H 33 | #define QMQTT_CLIENT_H 34 | 35 | #if defined(QMQTT_LIBRARY) 36 | # define QMQTTSHARED_EXPORT Q_DECL_EXPORT 37 | #else 38 | # define QMQTTSHARED_EXPORT Q_DECL_IMPORT 39 | #endif 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | namespace QMQTT { 47 | 48 | static const quint8 LIBRARY_VERSION_MAJOR = 0; 49 | static const quint8 LIBRARY_VERSION_MINOR = 3; 50 | static const quint8 LIBRARY_VERSION_REVISION = 1; 51 | //static const char* LIBRARY_VERSION = "0.3.1"; 52 | 53 | static const quint8 PROTOCOL_VERSION_MAJOR = 3; 54 | static const quint8 PROTOCOL_VERSION_MINOR = 1; 55 | static const quint8 PROTOCOL_VERSION_REVISION = 1; 56 | //static const char* PROTOCOL_VERSION = "MQTT/3.1"; 57 | 58 | enum ConnectionState 59 | { 60 | STATE_INIT = 0, 61 | STATE_CONNECTING, 62 | STATE_CONNECTED, 63 | STATE_DISCONNECTED 64 | }; 65 | 66 | enum ClientError 67 | { 68 | UnknownError = 0, 69 | SocketConnectionRefusedError, 70 | SocketRemoteHostClosedError, 71 | SocketHostNotFoundError, 72 | SocketAccessError, 73 | SocketResourceError, 74 | SocketTimeoutError, 75 | SocketDatagramTooLargeError, 76 | SocketNetworkError, 77 | SocketAddressInUseError, 78 | SocketAddressNotAvailableError, 79 | SocketUnsupportedSocketOperationError, 80 | SocketUnfinishedSocketOperationError, 81 | SocketProxyAuthenticationRequiredError, 82 | SocketSslHandshakeFailedError, 83 | SocketProxyConnectionRefusedError, 84 | SocketProxyConnectionClosedError, 85 | SocketProxyConnectionTimeoutError, 86 | SocketProxyNotFoundError, 87 | SocketProxyProtocolError, 88 | SocketOperationError, 89 | SocketSslInternalError, 90 | SocketSslInvalidUserDataError, 91 | SocketTemporaryError 92 | }; 93 | 94 | class ClientPrivate; 95 | class Message; 96 | class Frame; 97 | class NetworkInterface; 98 | 99 | class QMQTTSHARED_EXPORT Client : public QObject 100 | { 101 | Q_OBJECT 102 | Q_PROPERTY(quint16 _port READ port WRITE setPort) 103 | Q_PROPERTY(QHostAddress _host READ host WRITE setHost) 104 | Q_PROPERTY(QString _hostName READ hostName WRITE setHostName) 105 | Q_PROPERTY(QString _clientId READ clientId WRITE setClientId) 106 | Q_PROPERTY(QString _username READ username WRITE setUsername) 107 | Q_PROPERTY(QString _password READ password WRITE setPassword) 108 | Q_PROPERTY(quint16 _keepAlive READ keepAlive WRITE setKeepAlive) 109 | Q_PROPERTY(bool _autoReconnect READ autoReconnect WRITE setAutoReconnect) 110 | Q_PROPERTY(int _autoReconnectInterval READ autoReconnectInterval WRITE setAutoReconnectInterval) 111 | Q_PROPERTY(bool _cleanSession READ cleanSession WRITE setCleanSession) 112 | Q_PROPERTY(QString _willTopic READ willTopic WRITE setWillTopic) 113 | Q_PROPERTY(quint8 _willQos READ willQos WRITE setWillQos) 114 | Q_PROPERTY(bool _willRetain READ willRetain WRITE setWillRetain) 115 | Q_PROPERTY(QString _willMessage READ willMessage WRITE setWillMessage) 116 | Q_PROPERTY(QString _connectionState READ connectionState) 117 | 118 | public: 119 | Client(const QHostAddress& host = QHostAddress::LocalHost, 120 | const quint16 port = 1883, 121 | QObject* parent = NULL); 122 | 123 | Client(const QString& hostName, 124 | const quint16 port, 125 | const bool ssl, 126 | const bool ignoreSelfSigned, 127 | QObject* parent = NULL); 128 | 129 | // for testing purposes only 130 | Client(NetworkInterface* network, 131 | const QHostAddress& host = QHostAddress::LocalHost, 132 | const quint16 port = 1883, 133 | QObject* parent = NULL); 134 | 135 | virtual ~Client(); 136 | 137 | QHostAddress host() const; 138 | QString hostName() const; 139 | quint16 port() const; 140 | QString clientId() const; 141 | QString username() const; 142 | QString password() const; 143 | quint16 keepAlive() const; 144 | bool cleanSession() const; 145 | bool autoReconnect() const; 146 | int autoReconnectInterval() const; 147 | ConnectionState connectionState() const; 148 | QString willTopic() const; 149 | quint8 willQos() const; 150 | bool willRetain() const; 151 | QString willMessage() const; 152 | 153 | bool isConnectedToHost() const; 154 | 155 | public slots: 156 | void setHost(const QHostAddress& host); 157 | void setHostName(const QString& hostName); 158 | void setPort(const quint16 port); 159 | void setClientId(const QString& clientId); 160 | void setUsername(const QString& username); 161 | void setPassword(const QString& password); 162 | void setKeepAlive(const quint16 keepAlive); 163 | void setCleanSession(const bool cleanSession); 164 | void setAutoReconnect(const bool value); 165 | void setAutoReconnectInterval(const int autoReconnectInterval); 166 | void setWillTopic(const QString& willTopic); 167 | void setWillQos(const quint8 willQos); 168 | void setWillRetain(const bool willRetain); 169 | void setWillMessage(const QString& willMessage); 170 | 171 | void connectToHost(); 172 | void disconnectFromHost(); 173 | 174 | quint16 subscribe(const QString& topic, const quint8 qos); 175 | void unsubscribe(const QString& topic); 176 | 177 | quint16 publish(const Message& message); 178 | 179 | signals: 180 | void connected(); 181 | void disconnected(); 182 | void error(const QMQTT::ClientError error); 183 | 184 | // todo: should emit on server suback (or is that only at specific QoS levels?) 185 | void subscribed(const QString& topic); 186 | // todo: should emit on server unsuback (or is that only at specific QoS levels?) 187 | void unsubscribed(const QString& topic); 188 | // todo: should emit on server puback (or is that only at specific QoS levels?) 189 | void published(const QMQTT::Message& message); 190 | 191 | void received(const QMQTT::Message& message); 192 | 193 | protected slots: 194 | void onNetworkConnected(); 195 | void onNetworkDisconnected(); 196 | void onNetworkReceived(const QMQTT::Frame& frame); 197 | void onTimerPingReq(); 198 | void onNetworkError(QAbstractSocket::SocketError error); 199 | 200 | protected: 201 | QScopedPointer d_ptr; 202 | 203 | private: 204 | Q_DISABLE_COPY(Client) 205 | Q_DECLARE_PRIVATE(Client) 206 | }; 207 | 208 | } // namespace QMQTT 209 | 210 | Q_DECLARE_METATYPE(QMQTT::ClientError); 211 | 212 | #endif // QMQTT_CLIENT_H 213 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_client_p.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_client_p.cpp - qmqtt client private 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #include "qmqtt_client_p.h" 34 | #include "qmqtt_message.h" 35 | #include 36 | #include 37 | 38 | Q_LOGGING_CATEGORY(client, "qmqtt.client") 39 | 40 | static const quint8 QOS0 = 0x00; 41 | static const quint8 QOS1 = 0x01; 42 | static const quint8 QOS2 = 0x02; 43 | 44 | QMQTT::ClientPrivate::ClientPrivate(Client* qq_ptr) 45 | : _host(QHostAddress::LocalHost) 46 | , _port(1883) 47 | , _gmid(1) 48 | , _clientId(QUuid::createUuid().toString()) 49 | , _cleanSession(false) 50 | , _keepAlive(300) 51 | , _connectionState(STATE_INIT) 52 | , _willQos(0) 53 | , _willRetain(false) 54 | , q_ptr(qq_ptr) 55 | { 56 | } 57 | 58 | QMQTT::ClientPrivate::~ClientPrivate() 59 | { 60 | } 61 | 62 | void QMQTT::ClientPrivate::init(const QHostAddress& host, const quint16 port, NetworkInterface* network) 63 | { 64 | Q_Q(Client); 65 | 66 | _host = host; 67 | _port = port; 68 | if(network == NULL) 69 | { 70 | _network.reset(new Network); 71 | } 72 | else 73 | { 74 | _network.reset(network); 75 | } 76 | 77 | initializeErrorHash(); 78 | 79 | QObject::connect(&_timer, &QTimer::timeout, q, &Client::onTimerPingReq); 80 | QObject::connect(_network.data(), &Network::connected, 81 | q, &Client::onNetworkConnected); 82 | QObject::connect(_network.data(), &Network::disconnected, 83 | q, &Client::onNetworkDisconnected); 84 | QObject::connect(_network.data(), &Network::received, 85 | q, &Client::onNetworkReceived); 86 | QObject::connect(_network.data(), &Network::error, 87 | q, &Client::onNetworkError); 88 | } 89 | 90 | void QMQTT::ClientPrivate::init(const QString& hostName, const quint16 port, const bool ssl, const bool ignoreSelfSigned) 91 | { 92 | Q_Q(Client); 93 | 94 | _hostName = hostName; 95 | _port = port; 96 | if (ssl) 97 | { 98 | #ifndef QT_NO_SSL 99 | _network.reset(new SslNetwork(ignoreSelfSigned)); 100 | #else 101 | Q_UNUSED(ignoreSelfSigned) 102 | qCritical() << "SSL not supported in this QT build"; 103 | #endif // QT_NO_SSL 104 | } 105 | else 106 | { 107 | _network.reset(new Network); 108 | } 109 | 110 | initializeErrorHash(); 111 | 112 | QObject::connect(&_timer, &QTimer::timeout, q, &Client::onTimerPingReq); 113 | QObject::connect(_network.data(), &Network::connected, 114 | q, &Client::onNetworkConnected); 115 | QObject::connect(_network.data(), &Network::disconnected, 116 | q, &Client::onNetworkDisconnected); 117 | QObject::connect(_network.data(), &Network::received, 118 | q, &Client::onNetworkReceived); 119 | QObject::connect(_network.data(), &Network::error, 120 | q, &Client::onNetworkError); 121 | } 122 | 123 | void QMQTT::ClientPrivate::initializeErrorHash() 124 | { 125 | _socketErrorHash.insert(QAbstractSocket::ConnectionRefusedError, SocketConnectionRefusedError); 126 | _socketErrorHash.insert(QAbstractSocket::RemoteHostClosedError, SocketRemoteHostClosedError); 127 | _socketErrorHash.insert(QAbstractSocket::HostNotFoundError, SocketHostNotFoundError); 128 | _socketErrorHash.insert(QAbstractSocket::SocketAccessError, SocketAccessError); 129 | _socketErrorHash.insert(QAbstractSocket::SocketResourceError, SocketResourceError); 130 | _socketErrorHash.insert(QAbstractSocket::SocketTimeoutError, SocketTimeoutError); 131 | _socketErrorHash.insert(QAbstractSocket::DatagramTooLargeError, SocketDatagramTooLargeError); 132 | _socketErrorHash.insert(QAbstractSocket::NetworkError, SocketNetworkError); 133 | _socketErrorHash.insert(QAbstractSocket::AddressInUseError, SocketAddressInUseError); 134 | _socketErrorHash.insert(QAbstractSocket::SocketAddressNotAvailableError, SocketAddressNotAvailableError); 135 | _socketErrorHash.insert(QAbstractSocket::UnsupportedSocketOperationError, SocketUnsupportedSocketOperationError); 136 | _socketErrorHash.insert(QAbstractSocket::UnfinishedSocketOperationError, SocketUnfinishedSocketOperationError); 137 | _socketErrorHash.insert(QAbstractSocket::ProxyAuthenticationRequiredError, SocketProxyAuthenticationRequiredError); 138 | _socketErrorHash.insert(QAbstractSocket::SslHandshakeFailedError, SocketSslHandshakeFailedError); 139 | _socketErrorHash.insert(QAbstractSocket::ProxyConnectionRefusedError, SocketProxyConnectionRefusedError); 140 | _socketErrorHash.insert(QAbstractSocket::ProxyConnectionClosedError, SocketProxyConnectionClosedError); 141 | _socketErrorHash.insert(QAbstractSocket::ProxyConnectionTimeoutError, SocketProxyConnectionTimeoutError); 142 | _socketErrorHash.insert(QAbstractSocket::ProxyNotFoundError, SocketProxyNotFoundError); 143 | _socketErrorHash.insert(QAbstractSocket::ProxyProtocolError, SocketProxyProtocolError); 144 | _socketErrorHash.insert(QAbstractSocket::OperationError, SocketOperationError); 145 | _socketErrorHash.insert(QAbstractSocket::SslInternalError, SocketSslInternalError); 146 | _socketErrorHash.insert(QAbstractSocket::SslInvalidUserDataError, SocketSslInvalidUserDataError); 147 | _socketErrorHash.insert(QAbstractSocket::TemporaryError, SocketTemporaryError); 148 | } 149 | 150 | void QMQTT::ClientPrivate::connectToHost() 151 | { 152 | if (_hostName.isEmpty()) 153 | { 154 | _network->connectToHost(_host, _port); 155 | } 156 | else 157 | { 158 | _network->connectToHost(_hostName, _port); 159 | } 160 | } 161 | 162 | void QMQTT::ClientPrivate::onNetworkConnected() 163 | { 164 | Q_Q(Client); 165 | sendConnect(); 166 | startKeepAlive(); 167 | emit q->connected(); 168 | } 169 | 170 | void QMQTT::ClientPrivate::sendConnect() 171 | { 172 | quint8 header = CONNECT; 173 | quint8 flags = 0; 174 | 175 | //header 176 | Frame frame(header); 177 | 178 | //flags 179 | flags = FLAG_CLEANSESS(flags, _cleanSession ? 1 : 0 ); 180 | flags = FLAG_WILL(flags, willTopic().isEmpty() ? 0 : 1); 181 | if (!willTopic().isEmpty()) 182 | { 183 | flags = FLAG_WILLQOS(flags, willQos()); 184 | flags = FLAG_WILLRETAIN(flags, willRetain() ? 1 : 0); 185 | } 186 | if (!username().isEmpty()) 187 | { 188 | flags = FLAG_USERNAME(flags, 1); 189 | } 190 | if (!password().isEmpty()) 191 | { 192 | flags = FLAG_PASSWD(flags, 1); 193 | } 194 | 195 | //payload 196 | frame.writeString(QStringLiteral(PROTOCOL_MAGIC)); 197 | frame.writeChar(PROTOCOL_VERSION_MAJOR); 198 | frame.writeChar(flags); 199 | frame.writeInt(_keepAlive); 200 | frame.writeString(_clientId); 201 | if(!willTopic().isEmpty()) 202 | { 203 | frame.writeString(willTopic()); 204 | if(!willMessage().isEmpty()) 205 | { 206 | frame.writeString(willMessage()); 207 | } 208 | } 209 | if (!_username.isEmpty()) 210 | { 211 | frame.writeString(_username); 212 | } 213 | if (!_password.isEmpty()) 214 | { 215 | frame.writeString(_password); 216 | } 217 | _network->sendFrame(frame); 218 | } 219 | 220 | quint16 QMQTT::ClientPrivate::sendPublish(const Message& msg) 221 | { 222 | Message message(msg); 223 | 224 | quint8 header = PUBLISH; 225 | header = SETRETAIN(header, message.retain() ? 1 : 0); 226 | header = SETQOS(header, message.qos()); 227 | header = SETDUP(header, message.dup() ? 1 : 0); 228 | Frame frame(header); 229 | frame.writeString(message.topic()); 230 | if(message.qos() > QOS0) { 231 | if(message.id() == 0) { 232 | message.setId(nextmid()); 233 | } 234 | frame.writeInt(message.id()); 235 | } 236 | if(!message.payload().isEmpty()) { 237 | frame.writeRawData(message.payload()); 238 | } 239 | _network->sendFrame(frame); 240 | return message.id(); 241 | } 242 | 243 | void QMQTT::ClientPrivate::sendPuback(const quint8 type, const quint16 mid) 244 | { 245 | Frame frame(type); 246 | frame.writeInt(mid); 247 | _network->sendFrame(frame); 248 | } 249 | 250 | quint16 QMQTT::ClientPrivate::sendSubscribe(const QString & topic, const quint8 qos) 251 | { 252 | quint16 mid = nextmid(); 253 | Frame frame(SETQOS(SUBSCRIBE, QOS1)); 254 | frame.writeInt(mid); 255 | frame.writeString(topic); 256 | frame.writeChar(qos); 257 | _network->sendFrame(frame); 258 | return mid; 259 | } 260 | 261 | quint16 QMQTT::ClientPrivate::sendUnsubscribe(const QString &topic) 262 | { 263 | quint16 mid = nextmid(); 264 | Frame frame(SETQOS(UNSUBSCRIBE, QOS1)); 265 | frame.writeInt(mid); 266 | frame.writeString(topic); 267 | _network->sendFrame(frame); 268 | return mid; 269 | } 270 | 271 | void QMQTT::ClientPrivate::onTimerPingReq() 272 | { 273 | Frame frame(PINGREQ); 274 | _network->sendFrame(frame); 275 | } 276 | 277 | void QMQTT::ClientPrivate::disconnectFromHost() 278 | { 279 | sendDisconnect(); 280 | _network->disconnectFromHost(); 281 | } 282 | 283 | void QMQTT::ClientPrivate::sendDisconnect() 284 | { 285 | Frame frame(DISCONNECT); 286 | _network->sendFrame(frame); 287 | } 288 | 289 | void QMQTT::ClientPrivate::startKeepAlive() 290 | { 291 | _timer.setInterval(_keepAlive*1000); 292 | _timer.start(); 293 | } 294 | 295 | void QMQTT::ClientPrivate::stopKeepAlive() 296 | { 297 | _timer.stop(); 298 | } 299 | 300 | quint16 QMQTT::ClientPrivate::nextmid() 301 | { 302 | return _gmid++; 303 | } 304 | 305 | quint16 QMQTT::ClientPrivate::publish(const Message& message) 306 | { 307 | Q_Q(Client); 308 | quint16 msgid = sendPublish(message); 309 | emit q->published(message); 310 | return msgid; 311 | } 312 | 313 | void QMQTT::ClientPrivate::puback(const quint8 type, const quint16 msgid) 314 | { 315 | sendPuback(type, msgid); 316 | } 317 | 318 | quint16 QMQTT::ClientPrivate::subscribe(const QString& topic, const quint8 qos) 319 | { 320 | Q_Q(Client); 321 | quint16 msgid = sendSubscribe(topic, qos); 322 | emit q->subscribed(topic); 323 | return msgid; 324 | } 325 | 326 | void QMQTT::ClientPrivate::unsubscribe(const QString& topic) 327 | { 328 | Q_Q(Client); 329 | sendUnsubscribe(topic); 330 | emit q->unsubscribed(topic); 331 | } 332 | 333 | void QMQTT::ClientPrivate::onNetworkDisconnected() 334 | { 335 | Q_Q(Client); 336 | 337 | stopKeepAlive(); 338 | emit q->disconnected(); 339 | } 340 | 341 | void QMQTT::ClientPrivate::onNetworkReceived(const QMQTT::Frame& frm) 342 | { 343 | QMQTT::Frame frame(frm); 344 | quint8 qos = 0; 345 | bool retain, dup; 346 | QString topic; 347 | quint16 mid = 0; 348 | quint8 header = frame.header(); 349 | quint8 type = GETTYPE(header); 350 | Message message; 351 | 352 | switch(type) 353 | { 354 | case CONNACK: 355 | frame.readChar(); 356 | handleConnack(frame.readChar()); 357 | break; 358 | case PUBLISH: 359 | qos = GETQOS(header); 360 | retain = GETRETAIN(header); 361 | dup = GETDUP(header); 362 | topic = frame.readString(); 363 | if( qos > QOS0) { 364 | mid = frame.readInt(); 365 | } 366 | message.setId(mid); 367 | message.setTopic(topic); 368 | message.setPayload(frame.data()); 369 | message.setQos(qos); 370 | message.setRetain(retain); 371 | message.setDup(dup); 372 | handlePublish(message); 373 | break; 374 | case PUBACK: 375 | case PUBREC: 376 | case PUBREL: 377 | case PUBCOMP: 378 | mid = frame.readInt(); 379 | handlePuback(type, mid); 380 | break; 381 | case SUBACK: 382 | mid = frame.readInt(); 383 | qos = frame.readChar(); 384 | // todo: send a subscribed signal (only in certain cases? mid? qos?) 385 | break; 386 | case UNSUBACK: 387 | // todo: send an unsubscribed signal (only certain cases? mid?) 388 | break; 389 | case PINGRESP: 390 | // todo: I know I'm suppose to do something with this. Look at specifications. 391 | break; 392 | default: 393 | break; 394 | } 395 | } 396 | 397 | void QMQTT::ClientPrivate::handleConnack(const quint8 ack) 398 | { 399 | Q_UNUSED(ack); 400 | // todo: send connected signal 401 | } 402 | 403 | void QMQTT::ClientPrivate::handlePublish(const Message& message) 404 | { 405 | Q_Q(Client); 406 | 407 | if(message.qos() == QOS1) 408 | { 409 | sendPuback(PUBACK, message.id()); 410 | } 411 | else if(message.qos() == QOS2) 412 | { 413 | sendPuback(PUBREC, message.id()); 414 | } 415 | emit q->received(message); 416 | } 417 | 418 | void QMQTT::ClientPrivate::handlePuback(const quint8 type, const quint16 msgid) 419 | { 420 | if(type == PUBREC) 421 | { 422 | sendPuback(PUBREL, msgid); 423 | } 424 | else if (type == PUBREL) 425 | { 426 | sendPuback(PUBCOMP, msgid); 427 | } 428 | // todo: emit published signal (type? msgid?) 429 | } 430 | 431 | bool QMQTT::ClientPrivate::autoReconnect() const 432 | { 433 | return _network->autoReconnect(); 434 | } 435 | 436 | void QMQTT::ClientPrivate::setAutoReconnect(const bool autoReconnect) 437 | { 438 | _network->setAutoReconnect(autoReconnect); 439 | } 440 | 441 | bool QMQTT::ClientPrivate::autoReconnectInterval() const 442 | { 443 | return _network->autoReconnectInterval(); 444 | } 445 | 446 | void QMQTT::ClientPrivate::setAutoReconnectInterval(const int autoReconnectInterval) 447 | { 448 | _network->setAutoReconnectInterval(autoReconnectInterval); 449 | } 450 | 451 | bool QMQTT::ClientPrivate::isConnectedToHost() const 452 | { 453 | return _network->isConnectedToHost(); 454 | } 455 | 456 | QMQTT::ConnectionState QMQTT::ClientPrivate::connectionState() const 457 | { 458 | return _connectionState; 459 | } 460 | 461 | void QMQTT::ClientPrivate::setCleanSession(const bool cleanSession) 462 | { 463 | _cleanSession = cleanSession; 464 | } 465 | 466 | bool QMQTT::ClientPrivate::cleanSession() const 467 | { 468 | return _cleanSession; 469 | } 470 | 471 | void QMQTT::ClientPrivate::setKeepAlive(const quint16 keepAlive) 472 | { 473 | _keepAlive = keepAlive; 474 | } 475 | 476 | quint16 QMQTT::ClientPrivate::keepAlive() const 477 | { 478 | return _keepAlive; 479 | } 480 | 481 | void QMQTT::ClientPrivate::setPassword(const QString& password) 482 | { 483 | _password = password; 484 | } 485 | 486 | QString QMQTT::ClientPrivate::password() const 487 | { 488 | return _password; 489 | } 490 | 491 | void QMQTT::ClientPrivate::setUsername(const QString& username) 492 | { 493 | _username = username; 494 | } 495 | 496 | QString QMQTT::ClientPrivate::username() const 497 | { 498 | return _username; 499 | } 500 | 501 | void QMQTT::ClientPrivate::setClientId(const QString& clientId) 502 | { 503 | if(clientId.isEmpty()) 504 | { 505 | _clientId = QUuid::createUuid().toString(); 506 | } 507 | else 508 | { 509 | _clientId = clientId; 510 | } 511 | } 512 | 513 | QString QMQTT::ClientPrivate::clientId() const 514 | { 515 | return _clientId; 516 | } 517 | 518 | void QMQTT::ClientPrivate::setPort(const quint16 port) 519 | { 520 | _port = port; 521 | } 522 | 523 | quint16 QMQTT::ClientPrivate::port() const 524 | { 525 | return _port; 526 | } 527 | 528 | void QMQTT::ClientPrivate::setHost(const QHostAddress& host) 529 | { 530 | _host = host; 531 | } 532 | 533 | QHostAddress QMQTT::ClientPrivate::host() const 534 | { 535 | return _host; 536 | } 537 | 538 | void QMQTT::ClientPrivate::setHostName(const QString& hostName) 539 | { 540 | _hostName = hostName; 541 | } 542 | 543 | QString QMQTT::ClientPrivate::hostName() const 544 | { 545 | return _hostName; 546 | } 547 | 548 | QString QMQTT::ClientPrivate::willTopic() const 549 | { 550 | return _willTopic; 551 | } 552 | 553 | void QMQTT::ClientPrivate::setWillTopic(const QString& willTopic) 554 | { 555 | _willTopic = willTopic; 556 | } 557 | 558 | quint8 QMQTT::ClientPrivate::willQos() const 559 | { 560 | return _willQos; 561 | } 562 | 563 | void QMQTT::ClientPrivate::setWillQos(const quint8 willQos) 564 | { 565 | _willQos = willQos; 566 | } 567 | 568 | bool QMQTT::ClientPrivate::willRetain() const 569 | { 570 | return _willRetain; 571 | } 572 | 573 | void QMQTT::ClientPrivate::setWillRetain(const bool willRetain) 574 | { 575 | _willRetain = willRetain; 576 | } 577 | 578 | QString QMQTT::ClientPrivate::willMessage() const 579 | { 580 | return _willMessage; 581 | } 582 | 583 | void QMQTT::ClientPrivate::setWillMessage(const QString& willMessage) 584 | { 585 | _willMessage = willMessage; 586 | } 587 | 588 | void QMQTT::ClientPrivate::onNetworkError(QAbstractSocket::SocketError socketError) 589 | { 590 | Q_Q(Client); 591 | emit q->error(_socketErrorHash.value(socketError, UnknownError)); 592 | } 593 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_client_p.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_client_p.h - qmqtt client private header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_CLIENT_P_H 33 | #define QMQTT_CLIENT_P_H 34 | 35 | #include "qmqtt_client.h" 36 | #include "qmqtt_client_p.h" 37 | #include "qmqtt_network.h" 38 | #include "qmqtt_ssl_network.h" 39 | #include 40 | 41 | namespace QMQTT { 42 | 43 | class ClientPrivate 44 | { 45 | public: 46 | ClientPrivate(Client* qq_ptr); 47 | ~ClientPrivate(); 48 | 49 | void init(const QHostAddress& host, const quint16 port, NetworkInterface* network = NULL); 50 | void init(const QString& hostName, const quint16 port, const bool ssl, const bool ignoreSelfSigned); 51 | 52 | QHostAddress _host; 53 | QString _hostName; 54 | quint16 _port; 55 | quint16 _gmid; 56 | QString _clientId; 57 | QString _username; 58 | QString _password; 59 | bool _cleanSession; 60 | quint16 _keepAlive; 61 | ConnectionState _connectionState; 62 | QScopedPointer _network; 63 | QTimer _timer; 64 | QString _willTopic; 65 | quint8 _willQos; 66 | bool _willRetain; 67 | QString _willMessage; 68 | QHash _socketErrorHash; 69 | 70 | Client* const q_ptr; 71 | 72 | quint16 nextmid(); 73 | void connectToHost(); 74 | void sendConnect(); 75 | void onTimerPingReq(); 76 | quint16 sendUnsubscribe(const QString &topic); 77 | quint16 sendSubscribe(const QString &topic, const quint8 qos); 78 | quint16 sendPublish(const Message &msg); 79 | void sendPuback(const quint8 type, const quint16 mid); 80 | void sendDisconnect(); 81 | void disconnectFromHost(); 82 | void startKeepAlive(); 83 | void stopKeepAlive(); 84 | void onNetworkConnected(); 85 | void onNetworkDisconnected(); 86 | quint16 publish(const Message& message); 87 | void puback(const quint8 type, const quint16 msgid); 88 | quint16 subscribe(const QString& topic, const quint8 qos); 89 | void unsubscribe(const QString& topic); 90 | void onNetworkReceived(const QMQTT::Frame& frame); 91 | void handleConnack(const quint8 ack); 92 | void handlePublish(const Message& message); 93 | void handlePuback(const quint8 type, const quint16 msgid); 94 | bool autoReconnect() const; 95 | void setAutoReconnect(const bool autoReconnect); 96 | bool autoReconnectInterval() const; 97 | void setAutoReconnectInterval(const int autoReconnectInterval); 98 | bool isConnectedToHost() const; 99 | QMQTT::ConnectionState connectionState() const; 100 | void setCleanSession(const bool cleanSession); 101 | bool cleanSession() const; 102 | void setKeepAlive(const quint16 keepAlive); 103 | quint16 keepAlive() const; 104 | void setPassword(const QString& password); 105 | QString password() const; 106 | void setUsername(const QString& username); 107 | QString username() const; 108 | void setClientId(const QString& clientId); 109 | QString clientId() const; 110 | void setPort(const quint16 port); 111 | quint16 port() const; 112 | void setHost(const QHostAddress& host); 113 | QHostAddress host() const; 114 | void setHostName(const QString& hostName); 115 | QString hostName() const; 116 | void setWillTopic(const QString& willTopic); 117 | void setWillQos(const quint8 willQos); 118 | void setWillRetain(const bool willRetain); 119 | void setWillMessage(const QString& willMessage); 120 | QString willTopic() const; 121 | quint8 willQos() const; 122 | bool willRetain() const; 123 | QString willMessage() const; 124 | void initializeErrorHash(); 125 | void onNetworkError(QAbstractSocket::SocketError error); 126 | 127 | Q_DECLARE_PUBLIC(Client) 128 | }; 129 | 130 | } // namespace QMQTT 131 | 132 | #endif // QMQTT_CLIENT_P_H 133 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_frame.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_frame.cpp - qmqtt frame 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include 33 | #include 34 | #include "qmqtt_frame.h" 35 | 36 | namespace QMQTT { 37 | 38 | Q_LOGGING_CATEGORY(frame, "qmqtt.frame") 39 | 40 | Frame::Frame() 41 | : _header(0) 42 | , _data(QByteArray()) 43 | { 44 | } 45 | 46 | Frame::Frame(const quint8 header) 47 | : _header(header) 48 | , _data(QByteArray()) 49 | { 50 | } 51 | 52 | Frame::Frame(const quint8 header, const QByteArray &data) 53 | : _header(header) 54 | , _data(data) 55 | { 56 | } 57 | 58 | Frame::Frame(const Frame& other) 59 | { 60 | _header = other._header; 61 | _data = other._data; 62 | } 63 | 64 | Frame& Frame::operator=(const Frame& other) 65 | { 66 | _header = other._header; 67 | _data = other._data; 68 | return *this; 69 | } 70 | 71 | bool Frame::operator==(const Frame& other) const 72 | { 73 | return _header == other._header 74 | && _data == other._data; 75 | } 76 | 77 | 78 | Frame::~Frame() 79 | { 80 | } 81 | 82 | quint8 Frame::header() const 83 | { 84 | return _header; 85 | } 86 | 87 | QByteArray Frame::data() const 88 | { 89 | return _data; 90 | } 91 | 92 | quint8 Frame::readChar() 93 | { 94 | char c = _data.at(0); 95 | _data.remove(0, 1); 96 | return c; 97 | } 98 | 99 | quint16 Frame::readInt() 100 | { 101 | char msb = _data.at(0); 102 | char lsb = _data.at(1); 103 | _data.remove(0, 2); 104 | return (msb << 8) + lsb; 105 | } 106 | 107 | QString Frame::readString() 108 | { 109 | quint16 len = readInt(); 110 | QString s(_data.left(len)); 111 | _data.remove(0, len); 112 | return s; 113 | } 114 | 115 | void Frame::writeInt(const quint16 i) 116 | { 117 | _data.append(MSB(i)); 118 | _data.append(LSB(i)); 119 | } 120 | 121 | void Frame::writeString(const QString &string) 122 | { 123 | QByteArray data = string.toUtf8(); 124 | if (data.size() > (int)USHRT_MAX) 125 | { 126 | qCritical("qmqtt: String size bigger than %u bytes, truncate it!", USHRT_MAX); 127 | data.resize(USHRT_MAX); 128 | } 129 | writeInt(data.size()); 130 | _data.append(data); 131 | } 132 | 133 | void Frame::writeChar(const quint8 c) 134 | { 135 | _data.append(c); 136 | } 137 | 138 | void Frame::writeRawData(const QByteArray &data) 139 | { 140 | _data.append(data); 141 | } 142 | 143 | void Frame::write(QDataStream &stream) 144 | { 145 | QByteArray lenbuf; 146 | 147 | if (!encodeLength(lenbuf, _data.size())) 148 | { 149 | qCritical("qmqtt: Control packet bigger than 256 MB, dropped!"); 150 | return; 151 | } 152 | 153 | stream << (quint8)_header; 154 | if(_data.size() == 0) { 155 | stream << (quint8)0; 156 | return; 157 | } 158 | if (stream.writeRawData(lenbuf.data(), lenbuf.size()) != lenbuf.size()) 159 | { 160 | qCritical("qmqtt: Control packet write error!"); 161 | return; 162 | } 163 | if (stream.writeRawData(_data.data(), _data.size()) != _data.size()) 164 | { 165 | qCritical("qmqtt: Control packet write error!"); 166 | } 167 | } 168 | 169 | bool Frame::encodeLength(QByteArray &lenbuf, int length) 170 | { 171 | lenbuf.clear(); 172 | quint8 d; 173 | do { 174 | d = length % 128; 175 | length /= 128; 176 | if (length > 0) { 177 | d |= 0x80; 178 | } 179 | lenbuf.append(d); 180 | } while (length > 0); 181 | 182 | return lenbuf.size() <= 4; 183 | } 184 | 185 | } // namespace QMQTT 186 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_frame.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_frame.h - qmqtt frame heaer 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_FRAME_H 33 | #define QMQTT_FRAME_H 34 | 35 | #include 36 | 37 | #define PROTOCOL_MAGIC "MQIsdp" 38 | #define RANDOM_CLIENT_PREFIX "QMQTT-" 39 | 40 | #define CONNECT 0x10 41 | #define CONNACK 0x20 42 | #define PUBLISH 0x30 43 | #define PUBACK 0x40 44 | #define PUBREC 0x50 45 | #define PUBREL 0x60 46 | #define PUBCOMP 0x70 47 | #define SUBSCRIBE 0x80 48 | #define SUBACK 0x90 49 | #define UNSUBSCRIBE 0xA0 50 | #define UNSUBACK 0xB0 51 | #define PINGREQ 0xC0 52 | #define PINGRESP 0xD0 53 | #define DISCONNECT 0xE0 54 | 55 | #define LSB(A) (quint8)(A & 0x00FF) 56 | #define MSB(A) (quint8)((A & 0xFF00) >> 8) 57 | 58 | /* 59 | |-------------------------------------- 60 | | 7 6 5 4 | 3 | 2 1 | 0 | 61 | | Type | DUP flag | QoS | RETAIN | 62 | |-------------------------------------- 63 | */ 64 | #define GETTYPE(HDR) (HDR & 0xF0) 65 | #define SETQOS(HDR, Q) (HDR | ((Q) << 1)) 66 | #define GETQOS(HDR) ((HDR & 0x06) >> 1) 67 | #define SETDUP(HDR, D) (HDR | ((D) << 3)) 68 | #define GETDUP(HDR) ((HDR & 0x08) >> 3) 69 | #define SETRETAIN(HDR, R) (HDR | (R)) 70 | #define GETRETAIN(HDR) (HDR & 0x01) 71 | 72 | /* 73 | |---------------------------------------------------------------------------------- 74 | | 7 | 6 | 5 | 4 3 | 2 | 1 | 0 | 75 | | username | password | willretain | willqos | willflag | cleansession | reserved | 76 | |---------------------------------------------------------------------------------- 77 | */ 78 | #define FLAG_CLEANSESS(F, C) (F | ((C) << 1)) 79 | #define FLAG_WILL(F, W) (F | ((W) << 2)) 80 | #define FLAG_WILLQOS(F, Q) (F | ((Q) << 3)) 81 | #define FLAG_WILLRETAIN(F, R) (F | ((R) << 5)) 82 | #define FLAG_PASSWD(F, P) (F | ((P) << 6)) 83 | #define FLAG_USERNAME(F, U) (F | ((U) << 7)) 84 | 85 | namespace QMQTT { 86 | 87 | class Frame 88 | { 89 | public: 90 | explicit Frame(); 91 | explicit Frame(const quint8 header); 92 | explicit Frame(const quint8 header, const QByteArray &data); 93 | virtual ~Frame(); 94 | 95 | Frame(const Frame& other); 96 | Frame& operator=(const Frame& other); 97 | 98 | bool operator==(const Frame& other) const; 99 | 100 | quint8 header() const; 101 | QByteArray data() const; 102 | 103 | quint16 readInt(); 104 | quint8 readChar(); 105 | QString readString(); 106 | 107 | void writeInt(const quint16 i); 108 | void writeChar(const quint8 c); 109 | void writeString(const QString &string); 110 | void writeRawData(const QByteArray &data); 111 | 112 | //TODO: FIXME LATER 113 | void write(QDataStream &stream); 114 | bool encodeLength(QByteArray &lenbuf, int length); 115 | 116 | private: 117 | quint8 _header; 118 | QByteArray _data; 119 | }; 120 | 121 | } // namespace QMQTT 122 | 123 | Q_DECLARE_METATYPE(QMQTT::Frame); 124 | 125 | #endif // QMQTT_FRAME_H 126 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_global.h - qmqtt libray global 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_GLOBAL_H 33 | #define QMQTT_GLOBAL_H 34 | 35 | #if defined(QMQTT_LIBRARY) 36 | # define QMQTTSHARED_EXPORT Q_DECL_EXPORT 37 | #else 38 | # define QMQTTSHARED_EXPORT Q_DECL_IMPORT 39 | #endif 40 | 41 | #endif // QMQTT_GLOBAL_H 42 | 43 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_message.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_message.cpp - qmqtt message 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include "qmqtt_message.h" 33 | #include "qmqtt_message_p.h" 34 | 35 | QMQTT::Message::Message() 36 | : d_ptr(new MessagePrivate) 37 | { 38 | Q_D(Message); 39 | d->init(0, QString(), QByteArray(), 0, false, false); 40 | } 41 | 42 | QMQTT::Message::Message(const quint16 id, const QString &topic, const QByteArray &payload, 43 | const quint8 qos, const bool retain, const bool dup) 44 | : d_ptr(new MessagePrivate) 45 | { 46 | Q_D(Message); 47 | d->init(id, topic, payload, qos, retain, dup); 48 | } 49 | 50 | QMQTT::Message::~Message() 51 | { 52 | } 53 | 54 | QMQTT::Message::Message(const Message& other) 55 | : d_ptr(new MessagePrivate(*(other.d_ptr))) 56 | { 57 | } 58 | 59 | QMQTT::Message& QMQTT::Message::operator=(const Message& other) 60 | { 61 | Q_D(Message); 62 | *d = *(other.d_ptr); 63 | return *this; 64 | } 65 | 66 | bool QMQTT::Message::operator==(const Message& other) const 67 | { 68 | Q_D(const Message); 69 | return *d == *(other.d_ptr); 70 | } 71 | 72 | quint16 QMQTT::Message::id() const 73 | { 74 | Q_D(const Message); 75 | return d->id(); 76 | } 77 | 78 | void QMQTT::Message::setId(const quint16 id) 79 | { 80 | Q_D(Message); 81 | d->setId(id); 82 | } 83 | 84 | quint8 QMQTT::Message::qos() const 85 | { 86 | Q_D(const Message); 87 | return d->qos(); 88 | } 89 | 90 | void QMQTT::Message::setQos(const quint8 qos) 91 | { 92 | Q_D(Message); 93 | d->setQos(qos); 94 | } 95 | 96 | bool QMQTT::Message::retain() const 97 | { 98 | Q_D(const Message); 99 | return d->retain(); 100 | } 101 | 102 | void QMQTT::Message::setRetain(const bool retain) 103 | { 104 | Q_D(Message); 105 | d->setRetain(retain); 106 | } 107 | 108 | bool QMQTT::Message::dup() const 109 | { 110 | Q_D(const Message); 111 | return d->dup(); 112 | } 113 | 114 | void QMQTT::Message::setDup(const bool dup) 115 | { 116 | Q_D(Message); 117 | d->setDup(dup); 118 | } 119 | 120 | QString QMQTT::Message::topic() const 121 | { 122 | Q_D(const Message); 123 | return d->topic(); 124 | } 125 | 126 | void QMQTT::Message::setTopic(const QString& topic) 127 | { 128 | Q_D(Message); 129 | d->setTopic(topic); 130 | } 131 | 132 | QByteArray QMQTT::Message::payload() const 133 | { 134 | Q_D(const Message); 135 | return d->payload(); 136 | } 137 | 138 | void QMQTT::Message::setPayload(const QByteArray& payload) 139 | { 140 | Q_D(Message); 141 | d->setPayload(payload); 142 | } 143 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_message.h - qmqtt message header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_MESSAGE_H 33 | #define QMQTT_MESSAGE_H 34 | 35 | #if defined(QMQTT_LIBRARY) 36 | # define QMQTTSHARED_EXPORT Q_DECL_EXPORT 37 | #else 38 | # define QMQTTSHARED_EXPORT Q_DECL_IMPORT 39 | #endif 40 | 41 | #include 42 | #include 43 | 44 | namespace QMQTT { 45 | 46 | class MessagePrivate; 47 | 48 | class QMQTTSHARED_EXPORT Message 49 | { 50 | public: 51 | explicit Message(); 52 | explicit Message(const quint16 id, const QString &topic, const QByteArray &payload, 53 | const quint8 qos = 0, const bool retain = false, const bool dup = false); 54 | virtual ~Message(); 55 | 56 | Message(const Message& other); 57 | Message& operator=(const Message& other); 58 | 59 | bool operator==(const Message& other) const; 60 | 61 | quint16 id() const; 62 | void setId(const quint16 id); 63 | 64 | quint8 qos() const; 65 | void setQos(const quint8 qos); 66 | 67 | bool retain() const; 68 | void setRetain(const bool retain); 69 | 70 | bool dup() const; 71 | void setDup(const bool dup); 72 | 73 | QString topic() const; 74 | void setTopic(const QString &topic); 75 | 76 | QByteArray payload() const; 77 | void setPayload(const QByteArray & payload); 78 | 79 | protected: 80 | QScopedPointer d_ptr; 81 | 82 | private: 83 | Q_DECLARE_PRIVATE(Message) 84 | }; 85 | 86 | } // namespace QMQTT 87 | 88 | Q_DECLARE_METATYPE(QMQTT::Message); 89 | 90 | #endif // QMQTT_MESSAGE_H 91 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_message_p.cpp: -------------------------------------------------------------------------------- 1 | #include "qmqtt_message_p.h" 2 | 3 | QMQTT::MessagePrivate::MessagePrivate() 4 | : _id(0) 5 | , _qos(0) 6 | , _retain(false) 7 | , _dup(false) 8 | { 9 | } 10 | 11 | QMQTT::MessagePrivate::~MessagePrivate() 12 | { 13 | } 14 | 15 | void QMQTT::MessagePrivate::init(const quint16 id, const QString& topic, 16 | const QByteArray& payload, const quint8 qos, 17 | const bool retain, const bool dup) 18 | { 19 | _id = id; 20 | _topic = topic; 21 | _payload = payload; 22 | _qos = qos; 23 | _retain = retain; 24 | _dup = dup; 25 | } 26 | 27 | QMQTT::MessagePrivate::MessagePrivate(const MessagePrivate& other) 28 | { 29 | _id = other._id; 30 | _topic = other._topic; 31 | _payload = other._payload; 32 | _qos = other._qos; 33 | _retain = other._retain; 34 | _dup = other._dup; 35 | } 36 | 37 | QMQTT::MessagePrivate& QMQTT::MessagePrivate::operator=(const MessagePrivate& other) 38 | { 39 | if(this != &other) 40 | { 41 | _id = other._id; 42 | _topic = other._topic; 43 | _payload = other._payload; 44 | _qos = other._qos; 45 | _retain = other._retain; 46 | _dup = other._dup; 47 | } 48 | return *this; 49 | } 50 | 51 | bool QMQTT::MessagePrivate::operator==(const MessagePrivate& other) const 52 | { 53 | return _id == other._id 54 | && _topic == other._topic 55 | && _payload == other._payload 56 | && _qos == other._qos 57 | && _retain == other._retain 58 | && _dup == other._dup; 59 | } 60 | 61 | quint16 QMQTT::MessagePrivate::id() const 62 | { 63 | return _id; 64 | } 65 | 66 | void QMQTT::MessagePrivate::setId(const quint16 id) 67 | { 68 | _id = id; 69 | } 70 | 71 | quint8 QMQTT::MessagePrivate::qos() const 72 | { 73 | return _qos; 74 | } 75 | 76 | void QMQTT::MessagePrivate::setQos(const quint8 qos) 77 | { 78 | _qos = qos; 79 | } 80 | 81 | bool QMQTT::MessagePrivate::retain() const 82 | { 83 | return _retain; 84 | } 85 | 86 | void QMQTT::MessagePrivate::setRetain(const bool retain) 87 | { 88 | _retain = retain; 89 | } 90 | 91 | bool QMQTT::MessagePrivate::dup() const 92 | { 93 | return _dup; 94 | } 95 | void QMQTT::MessagePrivate::setDup(const bool dup) 96 | { 97 | _dup =dup; 98 | } 99 | 100 | QString QMQTT::MessagePrivate::topic() const 101 | { 102 | return _topic; 103 | } 104 | 105 | void QMQTT::MessagePrivate::setTopic(const QString& topic) 106 | { 107 | _topic = topic; 108 | } 109 | 110 | QByteArray QMQTT::MessagePrivate::payload() const 111 | { 112 | return _payload; 113 | } 114 | 115 | void QMQTT::MessagePrivate::setPayload(const QByteArray& payload) 116 | { 117 | _payload = payload; 118 | } 119 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_message_p.h: -------------------------------------------------------------------------------- 1 | #ifndef QMQTT_MESSAGE_P_H 2 | #define QMQTT_MESSAGE_P_H 3 | 4 | #include 5 | #include 6 | 7 | namespace QMQTT { 8 | 9 | class MessagePrivate 10 | { 11 | public: 12 | explicit MessagePrivate(); 13 | virtual ~MessagePrivate(); 14 | 15 | void init(const quint16 id, const QString &topic, const QByteArray &payload, 16 | const quint8 qos, const bool retain, const bool dup); 17 | 18 | MessagePrivate(const MessagePrivate& other); 19 | MessagePrivate& operator=(const MessagePrivate& other); 20 | bool operator==(const MessagePrivate& other) const; 21 | 22 | quint16 id() const; 23 | void setId(const quint16 id); 24 | quint8 qos() const; 25 | void setQos(const quint8 qos); 26 | bool retain() const; 27 | void setRetain(const bool retain); 28 | bool dup() const; 29 | void setDup(const bool dup); 30 | QString topic() const; 31 | void setTopic(const QString& topic); 32 | QByteArray payload() const; 33 | void setPayload(const QByteArray& payload); 34 | 35 | quint16 _id; 36 | QString _topic; 37 | QByteArray _payload; 38 | quint8 _qos; 39 | bool _retain; 40 | bool _dup; 41 | }; 42 | 43 | } // namespace QMQTT 44 | 45 | #endif // QMQTT_MESSAGE_P_H 46 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_network.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_network.cpp - qmqtt network 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include 33 | #include "qmqtt_network.h" 34 | #include "qmqtt_socket.h" 35 | #include "qmqtt_timer.h" 36 | 37 | const QHostAddress DEFAULT_HOST = QHostAddress::LocalHost; 38 | const quint16 DEFAULT_PORT = 1883; 39 | const bool DEFAULT_AUTORECONNECT = false; 40 | const int DEFAULT_AUTORECONNECT_INTERVAL_MS = 5000; 41 | 42 | QMQTT::Network::Network(QObject* parent) 43 | : NetworkInterface(parent) 44 | , _port(DEFAULT_PORT) 45 | , _host(DEFAULT_HOST) 46 | , _autoReconnect(DEFAULT_AUTORECONNECT) 47 | , _autoReconnectInterval(DEFAULT_AUTORECONNECT_INTERVAL_MS) 48 | , _bytesRemaining(0) 49 | , _socket(new QMQTT::Socket) 50 | , _autoReconnectTimer(new QMQTT::Timer) 51 | { 52 | initialize(); 53 | } 54 | 55 | QMQTT::Network::Network(SocketInterface* socketInterface, TimerInterface* timerInterface, 56 | QObject* parent) 57 | : NetworkInterface(parent) 58 | , _port(DEFAULT_PORT) 59 | , _host(DEFAULT_HOST) 60 | , _autoReconnect(DEFAULT_AUTORECONNECT) 61 | , _autoReconnectInterval(DEFAULT_AUTORECONNECT_INTERVAL_MS) 62 | , _bytesRemaining(0) 63 | , _socket(socketInterface) 64 | , _autoReconnectTimer(timerInterface) 65 | { 66 | initialize(); 67 | } 68 | 69 | void QMQTT::Network::initialize() 70 | { 71 | _socket->setParent(this); 72 | _autoReconnectTimer->setParent(this); 73 | _autoReconnectTimer->setSingleShot(true); 74 | _autoReconnectTimer->setInterval(_autoReconnectInterval); 75 | 76 | QObject::connect(_socket, &SocketInterface::connected, this, &Network::connected); 77 | QObject::connect(_socket, &SocketInterface::disconnected, this, &Network::onDisconnected); 78 | QObject::connect(_socket->ioDevice(), &QIODevice::readyRead, this, &Network::onSocketReadReady); 79 | QObject::connect( 80 | _autoReconnectTimer, &TimerInterface::timeout, 81 | this, static_cast(&Network::connectToHost)); 82 | QObject::connect(_socket, 83 | static_cast(&SocketInterface::error), 84 | this, &Network::onSocketError); 85 | } 86 | 87 | QMQTT::Network::~Network() 88 | { 89 | } 90 | 91 | bool QMQTT::Network::isConnectedToHost() const 92 | { 93 | return _socket->state() == QAbstractSocket::ConnectedState; 94 | } 95 | 96 | void QMQTT::Network::connectToHost(const QHostAddress& host, const quint16 port) 97 | { 98 | _host = host; 99 | _port = port; 100 | connectToHost(); 101 | } 102 | 103 | void QMQTT::Network::connectToHost(const QString& hostName, const quint16 port) 104 | { 105 | _hostName = hostName; 106 | _port = port; 107 | connectToHost(); 108 | } 109 | 110 | void QMQTT::Network::connectToHost() 111 | { 112 | _bytesRemaining = 0; 113 | if (_hostName.isEmpty()) 114 | { 115 | _socket->connectToHost(_host, _port); 116 | } 117 | else 118 | { 119 | _socket->connectToHost(_hostName, _port); 120 | } 121 | } 122 | 123 | void QMQTT::Network::onSocketError(QAbstractSocket::SocketError socketError) 124 | { 125 | emit error(socketError); 126 | if(_autoReconnect) 127 | { 128 | _autoReconnectTimer->start(); 129 | } 130 | } 131 | 132 | void QMQTT::Network::sendFrame(Frame& frame) 133 | { 134 | if(_socket->state() == QAbstractSocket::ConnectedState) 135 | { 136 | QDataStream out(_socket->ioDevice()); 137 | frame.write(out); 138 | } 139 | } 140 | 141 | void QMQTT::Network::disconnectFromHost() 142 | { 143 | _socket->disconnectFromHost(); 144 | } 145 | 146 | QAbstractSocket::SocketState QMQTT::Network::state() const 147 | { 148 | return _socket->state(); 149 | } 150 | 151 | bool QMQTT::Network::autoReconnect() const 152 | { 153 | return _autoReconnect; 154 | } 155 | 156 | void QMQTT::Network::setAutoReconnect(const bool autoReconnect) 157 | { 158 | _autoReconnect = autoReconnect; 159 | } 160 | 161 | int QMQTT::Network::autoReconnectInterval() const 162 | { 163 | return _autoReconnectInterval; 164 | } 165 | 166 | void QMQTT::Network::setAutoReconnectInterval(const int autoReconnectInterval) 167 | { 168 | _autoReconnectInterval = autoReconnectInterval; 169 | } 170 | 171 | void QMQTT::Network::onSocketReadReady() 172 | { 173 | QIODevice *ioDevice = _socket->ioDevice(); 174 | while(!ioDevice->atEnd()) 175 | { 176 | if(_bytesRemaining == 0) 177 | { 178 | if (!ioDevice->getChar(reinterpret_cast(&_header))) 179 | { 180 | // malformed packet 181 | emit error(QAbstractSocket::OperationError); 182 | ioDevice->close(); 183 | return; 184 | } 185 | 186 | _bytesRemaining = readRemainingLength(); 187 | if (_bytesRemaining < 0) 188 | { 189 | // malformed remaining length 190 | emit error(QAbstractSocket::OperationError); 191 | ioDevice->close(); 192 | return; 193 | } 194 | } 195 | 196 | QByteArray data = ioDevice->read(_bytesRemaining); 197 | _buffer.append(data); 198 | _bytesRemaining -= data.size(); 199 | 200 | if(_bytesRemaining == 0) 201 | { 202 | Frame frame(_header, _buffer); 203 | _buffer.clear(); 204 | emit received(frame); 205 | } 206 | } 207 | } 208 | 209 | int QMQTT::Network::readRemainingLength() 210 | { 211 | quint8 byte = 0; 212 | int length = 0; 213 | int multiplier = 1; 214 | QIODevice *ioDevice = _socket->ioDevice(); 215 | do { 216 | if (!ioDevice->getChar(reinterpret_cast(&byte))) 217 | return -1; 218 | length += (byte & 127) * multiplier; 219 | multiplier *= 128; 220 | if (multiplier > 128*128*128) 221 | return -1; 222 | } while ((byte & 128) != 0); 223 | 224 | return length; 225 | } 226 | 227 | void QMQTT::Network::onDisconnected() 228 | { 229 | emit disconnected(); 230 | if(_autoReconnect) 231 | { 232 | _autoReconnectTimer->start(); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_network.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_network.h - qmqtt network header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_NETWORK_H 33 | #define QMQTT_NETWORK_H 34 | 35 | #include "qmqtt_networkinterface.h" 36 | #include "qmqtt_frame.h" 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | namespace QMQTT { 45 | 46 | class SocketInterface; 47 | class TimerInterface; 48 | 49 | class Network : public NetworkInterface 50 | { 51 | Q_OBJECT 52 | 53 | public: 54 | Network(QObject* parent = NULL); 55 | Network(SocketInterface* socketInterface, TimerInterface* timerInterface, 56 | QObject* parent = NULL); 57 | ~Network(); 58 | 59 | void sendFrame(Frame& frame); 60 | bool isConnectedToHost() const; 61 | bool autoReconnect() const; 62 | void setAutoReconnect(const bool autoReconnect); 63 | QAbstractSocket::SocketState state() const; 64 | int autoReconnectInterval() const; 65 | void setAutoReconnectInterval(const int autoReconnectInterval); 66 | 67 | public slots: 68 | void connectToHost(const QHostAddress& host, const quint16 port); 69 | void connectToHost(const QString& hostName, const quint16 port); 70 | void disconnectFromHost(); 71 | 72 | protected slots: 73 | void onSocketError(QAbstractSocket::SocketError socketError); 74 | 75 | protected: 76 | void initialize(); 77 | int readRemainingLength(); 78 | 79 | quint16 _port; 80 | QHostAddress _host; 81 | QString _hostName; 82 | QByteArray _buffer; 83 | bool _autoReconnect; 84 | int _autoReconnectInterval; 85 | int _bytesRemaining; 86 | quint8 _header; 87 | SocketInterface* _socket; 88 | TimerInterface* _autoReconnectTimer; 89 | 90 | protected slots: 91 | void onSocketReadReady(); 92 | void onDisconnected(); 93 | void connectToHost(); 94 | 95 | private: 96 | Q_DISABLE_COPY(Network) 97 | }; 98 | 99 | } // namespace QMQTT 100 | 101 | #endif // QMQTT_NETWORK_H 102 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_networkinterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_network.h - qmqtt network header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_NETWORK_INTERFACE_H 33 | #define QMQTT_NETWORK_INTERFACE_H 34 | 35 | #include "qmqtt_frame.h" 36 | #include 37 | #include 38 | #include 39 | 40 | namespace QMQTT { 41 | 42 | class NetworkInterface : public QObject 43 | { 44 | Q_OBJECT 45 | public: 46 | explicit NetworkInterface(QObject* parent = NULL) : QObject(parent) {} 47 | virtual ~NetworkInterface() {} 48 | 49 | virtual void sendFrame(Frame& frame) = 0; 50 | virtual bool isConnectedToHost() const = 0; 51 | virtual bool autoReconnect() const = 0; 52 | virtual void setAutoReconnect(const bool autoReconnect) = 0; 53 | virtual int autoReconnectInterval() const = 0; 54 | virtual void setAutoReconnectInterval(const int autoReconnectInterval) = 0; 55 | virtual QAbstractSocket::SocketState state() const = 0; 56 | 57 | public slots: 58 | virtual void connectToHost(const QHostAddress& host, const quint16 port) = 0; 59 | virtual void connectToHost(const QString& hostName, const quint16 port) = 0; 60 | virtual void disconnectFromHost() = 0; 61 | 62 | signals: 63 | void connected(); 64 | void disconnected(); 65 | void received(const QMQTT::Frame& frame); 66 | void error(QAbstractSocket::SocketError error); 67 | }; 68 | 69 | } // namespace QMQTT 70 | 71 | #endif // QMQTT_NETWORK_INTERFACE_H 72 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_routedmessage.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_router.cpp - qmqtt router 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Router added by Niklas Wulf 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include "qmqtt_routedmessage.h" 34 | 35 | namespace QMQTT { 36 | 37 | RoutedMessage::RoutedMessage(const Message &message) : _message(message) 38 | { 39 | } 40 | 41 | const Message &RoutedMessage::message() const 42 | { 43 | return _message; 44 | } 45 | 46 | QHash RoutedMessage::parameters() const 47 | { 48 | return _parameters; 49 | } 50 | 51 | } // namespace QMQTT 52 | 53 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_routedmessage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_router.h - qmqtt router 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Router added by Niklas Wulf 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #ifndef QMQTT_ROUTEDMESSAGE_H 34 | #define QMQTT_ROUTEDMESSAGE_H 35 | 36 | #include 37 | #include 38 | #include "qmqtt_message.h" 39 | 40 | namespace QMQTT { 41 | 42 | class Message; 43 | 44 | class RoutedMessage 45 | { 46 | public: 47 | explicit RoutedMessage(const Message &message); 48 | 49 | const Message &message() const; 50 | QHash parameters() const; 51 | 52 | private: 53 | friend class RouteSubscription; 54 | 55 | Message _message; 56 | QHash _parameters; 57 | }; 58 | 59 | } // namespace QMQTT 60 | 61 | #endif // QMQTT_ROUTEDMESSAGE_H 62 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_router.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_router.cpp - qmqtt router 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Router added by Niklas Wulf 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include "qmqtt_router.h" 34 | 35 | #include "qmqtt_client.h" 36 | #include "qmqtt_routesubscription.h" 37 | #include 38 | 39 | namespace QMQTT { 40 | 41 | Q_LOGGING_CATEGORY(router, "qmqtt.router") 42 | 43 | Router::Router(Client *parent) : QObject(parent), _client(parent) 44 | { 45 | } 46 | 47 | RouteSubscription *Router::subscribe(const QString &route) 48 | { 49 | RouteSubscription *subscription = new RouteSubscription(this); 50 | subscription->setRoute(route); 51 | _client->subscribe(subscription->_topic, 0); 52 | connect(_client, &Client::received, subscription, &RouteSubscription::routeMessage); 53 | return subscription; 54 | } 55 | 56 | } // namespace QMQTT 57 | 58 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_router.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_router.h - qmqtt router 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Router added by Niklas Wulf 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #ifndef QMQTT_ROUTER_H 34 | #define QMQTT_ROUTER_H 35 | 36 | #include 37 | 38 | namespace QMQTT { 39 | 40 | class Client; 41 | class RouteSubscription; 42 | 43 | class Router : public QObject 44 | { 45 | Q_OBJECT 46 | public: 47 | explicit Router(Client *parent = 0); 48 | 49 | RouteSubscription *subscribe(const QString &route); 50 | 51 | private: 52 | Client *_client; 53 | }; 54 | 55 | } // namespace QMQTT 56 | 57 | #endif // QMQTT_ROUTER_H 58 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_routesubscription.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_router.cpp - qmqtt router 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Router added by Niklas Wulf 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include "qmqtt_routesubscription.h" 34 | 35 | #include "qmqtt_message.h" 36 | #include "qmqtt_router.h" 37 | #include "qmqtt_routedmessage.h" 38 | #include 39 | 40 | namespace QMQTT { 41 | 42 | Q_LOGGING_CATEGORY(routerSubscription, "qmqtt.routersubscription") 43 | 44 | RouteSubscription::RouteSubscription(Router *parent) : QObject(parent) 45 | { 46 | } 47 | 48 | QString RouteSubscription::route() const 49 | { 50 | return _topic; 51 | } 52 | 53 | void RouteSubscription::setRoute(const QString &route) 54 | { 55 | QRegularExpression parameterNamesRegExp("\\:([a-zA-Z0-9]+)"); // note how names must not contain dashes or underscores 56 | 57 | // Remove paramter names to get the actual topic "route" 58 | QString topic = route; 59 | topic.replace(parameterNamesRegExp, ""); 60 | 61 | // Remove the MQTT wildcards to get a regular expression, which matches the parameters 62 | QString parameterRegExp = route; 63 | parameterRegExp 64 | .replace("+", "") 65 | .replace(parameterNamesRegExp, "([a-zA-Z0-9_-]+)") // note how parameter values may contain dashes or underscores 66 | .replace("#", "") 67 | .replace("$", "\\$"); 68 | 69 | // Extract the parameter names 70 | QRegularExpressionMatchIterator it = parameterNamesRegExp.globalMatch(route); 71 | QStringList names; 72 | while(it.hasNext()) { 73 | QRegularExpressionMatch match = it.next(); 74 | QString parameterName = match.captured(1); 75 | names << parameterName; 76 | } 77 | 78 | _topic = topic; 79 | _parameterNames = names; 80 | _regularExpression = QRegularExpression(parameterRegExp); 81 | } 82 | 83 | void RouteSubscription::routeMessage(const Message &message) 84 | { 85 | QString topic = message.topic(); 86 | QRegularExpressionMatch match = _regularExpression.match(topic); 87 | if(!match.hasMatch()) { 88 | return; 89 | } 90 | 91 | RoutedMessage routedMessage(message); 92 | 93 | for(int i = 0, c = _parameterNames.size(); i < c; ++i) { 94 | QString name = _parameterNames.at(i); 95 | QString value = match.captured(i + 1); 96 | 97 | routedMessage._parameters.insert(name, value); 98 | } 99 | 100 | emit received(routedMessage); 101 | } 102 | 103 | } // namespace QMQTT 104 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_routesubscription.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_router.h - qmqtt router 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Router added by Niklas Wulf 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #ifndef QMQTT_ROUTESUBSCRIPTION_H 34 | #define QMQTT_ROUTESUBSCRIPTION_H 35 | 36 | #include 37 | #include 38 | 39 | namespace QMQTT { 40 | 41 | class Message; 42 | class RoutedMessage; 43 | class Router; 44 | 45 | class RouteSubscription : public QObject 46 | { 47 | Q_OBJECT 48 | public: 49 | QString route() const; 50 | 51 | signals: 52 | void received(const RoutedMessage &message); 53 | 54 | private slots: 55 | void routeMessage(const Message &message); 56 | 57 | private: 58 | friend class Router; 59 | explicit RouteSubscription(Router *parent = 0); 60 | void setRoute(const QString &route); 61 | 62 | QString _topic; 63 | QRegularExpression _regularExpression; 64 | QStringList _parameterNames; 65 | }; 66 | 67 | } // namespace QMQTT 68 | 69 | #endif // QMQTT_ROUTESUBSCRIPTION_H 70 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_socket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_socket.cpp - qmqtt socket 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include "qmqtt_socket.h" 33 | #include 34 | 35 | QMQTT::Socket::Socket(QObject* parent) 36 | : SocketInterface(parent) 37 | , _socket(new QTcpSocket) 38 | { 39 | connect(_socket.data(), &QTcpSocket::connected, this, &SocketInterface::connected); 40 | connect(_socket.data(), &QTcpSocket::disconnected, this, &SocketInterface::disconnected); 41 | connect(_socket.data(), 42 | static_cast(&QTcpSocket::error), 43 | this, 44 | static_cast(&SocketInterface::error)); 45 | } 46 | 47 | QMQTT::Socket::~Socket() 48 | { 49 | } 50 | 51 | QIODevice *QMQTT::Socket::ioDevice() 52 | { 53 | return _socket.data(); 54 | } 55 | 56 | void QMQTT::Socket::connectToHost(const QHostAddress& address, quint16 port) 57 | { 58 | _socket->connectToHost(address, port); 59 | } 60 | 61 | void QMQTT::Socket::connectToHost(const QString& hostName, quint16 port) 62 | { 63 | _socket->connectToHost(hostName, port); 64 | } 65 | 66 | void QMQTT::Socket::disconnectFromHost() 67 | { 68 | _socket->disconnectFromHost(); 69 | } 70 | 71 | QAbstractSocket::SocketState QMQTT::Socket::state() const 72 | { 73 | return _socket->state(); 74 | } 75 | 76 | QAbstractSocket::SocketError QMQTT::Socket::error() const 77 | { 78 | return _socket->error(); 79 | } 80 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_socket.h - qmqtt socket header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_SOCKET_H 33 | #define QMQTT_SOCKET_H 34 | 35 | #include "qmqtt_socketinterface.h" 36 | #include 37 | #include 38 | 39 | class QTcpSocket; 40 | 41 | namespace QMQTT 42 | { 43 | 44 | class Socket : public SocketInterface 45 | { 46 | Q_OBJECT 47 | public: 48 | explicit Socket(QObject* parent = NULL); 49 | virtual ~Socket(); 50 | 51 | virtual QIODevice *ioDevice(); 52 | void connectToHost(const QHostAddress& address, quint16 port); 53 | void connectToHost(const QString& hostName, quint16 port); 54 | void disconnectFromHost(); 55 | QAbstractSocket::SocketState state() const; 56 | QAbstractSocket::SocketError error() const; 57 | 58 | protected: 59 | QScopedPointer _socket; 60 | }; 61 | 62 | } 63 | 64 | #endif // QMQTT_SOCKET_H 65 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_socketinterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_socketinterface.h - qmqtt socket interface header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_SOCKET_INTERFACE_H 33 | #define QMQTT_SOCKET_INTERFACE_H 34 | 35 | #include 36 | #include 37 | 38 | namespace QMQTT 39 | { 40 | 41 | class SocketInterface : public QObject 42 | { 43 | Q_OBJECT 44 | public: 45 | explicit SocketInterface(QObject* parent = NULL) : QObject(parent) {} 46 | virtual ~SocketInterface() {} 47 | 48 | virtual QIODevice *ioDevice() = 0; 49 | virtual void connectToHost(const QHostAddress& address, quint16 port) = 0; 50 | virtual void connectToHost(const QString& hostName, quint16 port) = 0; 51 | virtual void disconnectFromHost() = 0; 52 | virtual QAbstractSocket::SocketState state() const = 0; 53 | virtual QAbstractSocket::SocketError error() const = 0; 54 | 55 | signals: 56 | void connected(); 57 | void disconnected(); 58 | void error(QAbstractSocket::SocketError socketError); 59 | }; 60 | 61 | } 62 | 63 | #endif // QMQTT_SOCKET_INTERFACE_H 64 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_ssl_network.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_ssl_network.cpp - qmqtt SSL network 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Copyright (c) 2016 Matthias Dieter Wallnöfer 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include 34 | #include "qmqtt_ssl_network.h" 35 | #include "qmqtt_ssl_socket.h" 36 | #include "qmqtt_timer.h" 37 | 38 | #ifndef QT_NO_SSL 39 | 40 | const QString DEFAULT_HOST_NAME = QStringLiteral("localhost"); 41 | const quint16 DEFAULT_PORT = 8883; 42 | const bool DEFAULT_AUTORECONNECT = false; 43 | const int DEFAULT_AUTORECONNECT_INTERVAL_MS = 5000; 44 | 45 | QMQTT::SslNetwork::SslNetwork(bool ignoreSelfSigned, QObject* parent) 46 | : NetworkInterface(parent) 47 | , _port(DEFAULT_PORT) 48 | , _hostName(DEFAULT_HOST_NAME) 49 | , _autoReconnect(DEFAULT_AUTORECONNECT) 50 | , _autoReconnectInterval(DEFAULT_AUTORECONNECT_INTERVAL_MS) 51 | , _bytesRemaining(0) 52 | , _socket(new QMQTT::SslSocket(ignoreSelfSigned)) 53 | , _autoReconnectTimer(new QMQTT::Timer) 54 | { 55 | initialize(); 56 | } 57 | 58 | QMQTT::SslNetwork::SslNetwork(SocketInterface* socketInterface, TimerInterface* timerInterface, 59 | QObject* parent) 60 | : NetworkInterface(parent) 61 | , _port(DEFAULT_PORT) 62 | , _hostName(DEFAULT_HOST_NAME) 63 | , _autoReconnect(DEFAULT_AUTORECONNECT) 64 | , _autoReconnectInterval(DEFAULT_AUTORECONNECT_INTERVAL_MS) 65 | , _bytesRemaining(0) 66 | , _socket(socketInterface) 67 | , _autoReconnectTimer(timerInterface) 68 | { 69 | initialize(); 70 | } 71 | 72 | void QMQTT::SslNetwork::initialize() 73 | { 74 | _socket->setParent(this); 75 | _autoReconnectTimer->setParent(this); 76 | _autoReconnectTimer->setSingleShot(true); 77 | _autoReconnectTimer->setInterval(_autoReconnectInterval); 78 | 79 | QObject::connect(_socket, &SocketInterface::connected, this, &SslNetwork::connected); 80 | QObject::connect(_socket, &SocketInterface::disconnected, this, &SslNetwork::onDisconnected); 81 | QObject::connect(_socket->ioDevice(), &QIODevice::readyRead, this, &SslNetwork::onSocketReadReady); 82 | QObject::connect( 83 | _autoReconnectTimer, &TimerInterface::timeout, 84 | this, static_cast(&SslNetwork::connectToHost)); 85 | QObject::connect(_socket, 86 | static_cast(&SocketInterface::error), 87 | this, &SslNetwork::onSocketError); 88 | } 89 | 90 | QMQTT::SslNetwork::~SslNetwork() 91 | { 92 | } 93 | 94 | bool QMQTT::SslNetwork::isConnectedToHost() const 95 | { 96 | return _socket->state() == QAbstractSocket::ConnectedState; 97 | } 98 | 99 | void QMQTT::SslNetwork::connectToHost(const QHostAddress& host, const quint16 port) 100 | { 101 | Q_UNUSED(host); 102 | Q_UNUSED(port); 103 | 104 | qCritical("qmqtt: SSL does not work with host addresses!"); 105 | emit error(QAbstractSocket::ConnectionRefusedError); 106 | } 107 | 108 | void QMQTT::SslNetwork::connectToHost(const QString& hostName, const quint16 port) 109 | { 110 | _hostName = hostName; 111 | _port = port; 112 | connectToHost(); 113 | } 114 | 115 | void QMQTT::SslNetwork::connectToHost() 116 | { 117 | _bytesRemaining = 0; 118 | _socket->connectToHost(_hostName, _port); 119 | } 120 | 121 | void QMQTT::SslNetwork::onSocketError(QAbstractSocket::SocketError socketError) 122 | { 123 | emit error(socketError); 124 | if(_autoReconnect) 125 | { 126 | _autoReconnectTimer->start(); 127 | } 128 | } 129 | 130 | void QMQTT::SslNetwork::sendFrame(Frame& frame) 131 | { 132 | if(_socket->state() == QAbstractSocket::ConnectedState) 133 | { 134 | QDataStream out(_socket->ioDevice()); 135 | frame.write(out); 136 | } 137 | } 138 | 139 | void QMQTT::SslNetwork::disconnectFromHost() 140 | { 141 | _socket->disconnectFromHost(); 142 | } 143 | 144 | QAbstractSocket::SocketState QMQTT::SslNetwork::state() const 145 | { 146 | return _socket->state(); 147 | } 148 | 149 | bool QMQTT::SslNetwork::autoReconnect() const 150 | { 151 | return _autoReconnect; 152 | } 153 | 154 | void QMQTT::SslNetwork::setAutoReconnect(const bool autoReconnect) 155 | { 156 | _autoReconnect = autoReconnect; 157 | } 158 | 159 | int QMQTT::SslNetwork::autoReconnectInterval() const 160 | { 161 | return _autoReconnectInterval; 162 | } 163 | 164 | void QMQTT::SslNetwork::setAutoReconnectInterval(const int autoReconnectInterval) 165 | { 166 | _autoReconnectInterval = autoReconnectInterval; 167 | } 168 | 169 | void QMQTT::SslNetwork::onSocketReadReady() 170 | { 171 | QIODevice *ioDevice = _socket->ioDevice(); 172 | while(!ioDevice->atEnd()) 173 | { 174 | if(_bytesRemaining == 0) 175 | { 176 | if (!ioDevice->getChar(reinterpret_cast(&_header))) 177 | { 178 | // malformed packet 179 | emit error(QAbstractSocket::OperationError); 180 | ioDevice->close(); 181 | return; 182 | } 183 | 184 | _bytesRemaining = readRemainingLength(); 185 | if (_bytesRemaining < 0) 186 | { 187 | // malformed remaining length 188 | emit error(QAbstractSocket::OperationError); 189 | ioDevice->close(); 190 | return; 191 | } 192 | } 193 | 194 | QByteArray data = ioDevice->read(_bytesRemaining); 195 | _buffer.append(data); 196 | _bytesRemaining -= data.size(); 197 | 198 | if(_bytesRemaining == 0) 199 | { 200 | Frame frame(_header, _buffer); 201 | _buffer.clear(); 202 | emit received(frame); 203 | } 204 | } 205 | } 206 | 207 | int QMQTT::SslNetwork::readRemainingLength() 208 | { 209 | quint8 byte = 0; 210 | int length = 0; 211 | int multiplier = 1; 212 | QIODevice *ioDevice = _socket->ioDevice(); 213 | do { 214 | if (!ioDevice->getChar(reinterpret_cast(&byte))) 215 | return -1; 216 | length += (byte & 127) * multiplier; 217 | multiplier *= 128; 218 | if (multiplier > 128*128*128) 219 | return -1; 220 | } while ((byte & 128) != 0); 221 | 222 | return length; 223 | } 224 | 225 | void QMQTT::SslNetwork::onDisconnected() 226 | { 227 | emit disconnected(); 228 | if(_autoReconnect) 229 | { 230 | _autoReconnectTimer->start(); 231 | } 232 | } 233 | 234 | #endif // QT_NO_SSL 235 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_ssl_network.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_ssl_network.h - qmqtt SSL network header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Copyright (c) 2016 Matthias Dieter Wallnöfer 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #ifndef QMQTT_SSL_NETWORK_H 34 | #define QMQTT_SSL_NETWORK_H 35 | 36 | #include "qmqtt_networkinterface.h" 37 | #include "qmqtt_frame.h" 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #ifndef QT_NO_SSL 46 | 47 | namespace QMQTT { 48 | 49 | class SocketInterface; 50 | class TimerInterface; 51 | 52 | class SslNetwork : public NetworkInterface 53 | { 54 | Q_OBJECT 55 | 56 | public: 57 | SslNetwork(bool ignoreSelfSigned, QObject* parent = NULL); 58 | SslNetwork(SocketInterface* socketInterface, TimerInterface* timerInterface, 59 | QObject* parent = NULL); 60 | ~SslNetwork(); 61 | 62 | void sendFrame(Frame& frame); 63 | bool isConnectedToHost() const; 64 | bool autoReconnect() const; 65 | void setAutoReconnect(const bool autoReconnect); 66 | QAbstractSocket::SocketState state() const; 67 | int autoReconnectInterval() const; 68 | void setAutoReconnectInterval(const int autoReconnectInterval); 69 | 70 | public slots: 71 | void connectToHost(const QHostAddress& host, const quint16 port); 72 | void connectToHost(const QString& hostName, const quint16 port); 73 | void disconnectFromHost(); 74 | 75 | protected slots: 76 | void onSocketError(QAbstractSocket::SocketError socketError); 77 | 78 | protected: 79 | void initialize(); 80 | int readRemainingLength(); 81 | 82 | quint16 _port; 83 | QString _hostName; 84 | QByteArray _buffer; 85 | bool _autoReconnect; 86 | int _autoReconnectInterval; 87 | int _bytesRemaining; 88 | quint8 _header; 89 | SocketInterface* _socket; 90 | TimerInterface* _autoReconnectTimer; 91 | 92 | protected slots: 93 | void onSocketReadReady(); 94 | void onDisconnected(); 95 | void connectToHost(); 96 | 97 | private: 98 | Q_DISABLE_COPY(SslNetwork) 99 | }; 100 | 101 | } // namespace QMQTT 102 | 103 | #endif // QT_NO_SSL 104 | 105 | #endif // QMQTT_SSL_NETWORK_H 106 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_ssl_socket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_ssl_socket.cpp - qmqtt SSL socket 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Copyright (c) 2016 Matthias Dieter Wallnöfer 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #include "qmqtt_ssl_socket.h" 34 | #include 35 | 36 | #ifndef QT_NO_SSL 37 | 38 | QMQTT::SslSocket::SslSocket(bool ignoreSelfSigned, QObject* parent) 39 | : SocketInterface(parent) 40 | , _socket(new QSslSocket) 41 | , _ignoreSelfSigned(ignoreSelfSigned) 42 | { 43 | connect(_socket.data(), &QSslSocket::encrypted, this, &SocketInterface::connected); 44 | connect(_socket.data(), &QSslSocket::disconnected, this, &SocketInterface::disconnected); 45 | connect(_socket.data(), 46 | static_cast(&QSslSocket::error), 47 | this, 48 | static_cast(&SocketInterface::error)); 49 | connect(_socket.data(), 50 | static_cast&)>(&QSslSocket::sslErrors), 51 | this, 52 | &SslSocket::sslErrors); 53 | } 54 | 55 | QMQTT::SslSocket::~SslSocket() 56 | { 57 | } 58 | 59 | QIODevice *QMQTT::SslSocket::ioDevice() 60 | { 61 | return _socket.data(); 62 | } 63 | 64 | void QMQTT::SslSocket::connectToHost(const QHostAddress& address, quint16 port) 65 | { 66 | Q_UNUSED(address); 67 | Q_UNUSED(port); 68 | 69 | qCritical("qmqtt: SSL does not work with host addresses!"); 70 | emit _socket->error(QAbstractSocket::ConnectionRefusedError); 71 | } 72 | 73 | void QMQTT::SslSocket::connectToHost(const QString& hostName, quint16 port) 74 | { 75 | _socket->connectToHostEncrypted(hostName, port); 76 | if (!_socket->waitForEncrypted()) 77 | { 78 | qCritical() << QStringLiteral("qmqtt SSL: ") << _socket->errorString(); 79 | } 80 | } 81 | 82 | void QMQTT::SslSocket::disconnectFromHost() 83 | { 84 | _socket->disconnectFromHost(); 85 | } 86 | 87 | QAbstractSocket::SocketState QMQTT::SslSocket::state() const 88 | { 89 | return _socket->state(); 90 | } 91 | 92 | QAbstractSocket::SocketError QMQTT::SslSocket::error() const 93 | { 94 | return _socket->error(); 95 | } 96 | 97 | void QMQTT::SslSocket::sslErrors(const QList &errors) 98 | { 99 | Q_UNUSED(errors); 100 | 101 | if (_ignoreSelfSigned) 102 | { 103 | // allow self-signed certificates 104 | _socket->ignoreSslErrors(); 105 | } 106 | } 107 | 108 | #endif // QT_NO_SSL 109 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_ssl_socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_ssl_socket.h - qmqtt SSL socket header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * Copyright (c) 2016 Matthias Dieter Wallnöfer 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of mqttc nor the names of its contributors may be used 17 | * to endorse or promote products derived from this software without 18 | * specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | #ifndef QMQTT_SSL_SOCKET_H 34 | #define QMQTT_SSL_SOCKET_H 35 | 36 | #include "qmqtt_socketinterface.h" 37 | #include 38 | #include 39 | 40 | #ifndef QT_NO_SSL 41 | 42 | class QSslSocket; 43 | class QSslError; 44 | 45 | namespace QMQTT 46 | { 47 | 48 | class SslSocket : public SocketInterface 49 | { 50 | Q_OBJECT 51 | public: 52 | explicit SslSocket(bool ignoreSelfSigned, QObject* parent = NULL); 53 | virtual ~SslSocket(); 54 | 55 | virtual QIODevice *ioDevice(); 56 | void connectToHost(const QHostAddress& address, quint16 port); 57 | void connectToHost(const QString& hostName, quint16 port); 58 | void disconnectFromHost(); 59 | QAbstractSocket::SocketState state() const; 60 | QAbstractSocket::SocketError error() const; 61 | 62 | protected slots: 63 | void sslErrors(const QList &errors); 64 | 65 | protected: 66 | QScopedPointer _socket; 67 | bool _ignoreSelfSigned; 68 | }; 69 | 70 | } 71 | 72 | #endif // QT_NO_SSL 73 | 74 | #endif // QMQTT_SSL_SOCKET_H 75 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_timer.cpp - qmqtt timer 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include "qmqtt_timer.h" 33 | 34 | QMQTT::Timer::Timer(QObject* parent) 35 | : TimerInterface(parent) 36 | { 37 | connect(&_timer, &QTimer::timeout, this, &TimerInterface::timeout); 38 | } 39 | 40 | QMQTT::Timer::~Timer() 41 | { 42 | } 43 | 44 | bool QMQTT::Timer::isSingleShot() const 45 | { 46 | return _timer.isSingleShot(); 47 | } 48 | 49 | void QMQTT::Timer::setSingleShot(bool singleShot) 50 | { 51 | _timer.setSingleShot(singleShot); 52 | } 53 | 54 | int QMQTT::Timer::interval() const 55 | { 56 | return _timer.interval(); 57 | } 58 | 59 | void QMQTT::Timer::setInterval(int msec) 60 | { 61 | _timer.setInterval(msec); 62 | } 63 | 64 | void QMQTT::Timer::start() 65 | { 66 | _timer.start(); 67 | } 68 | 69 | void QMQTT::Timer::stop() 70 | { 71 | _timer.stop(); 72 | } 73 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_timer.h - qmqtt timer header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_TIMER_H 33 | #define QMQTT_TIMER_H 34 | 35 | #include "qmqtt_timerinterface.h" 36 | #include 37 | 38 | namespace QMQTT { 39 | 40 | class Timer : public TimerInterface 41 | { 42 | Q_OBJECT 43 | public: 44 | explicit Timer(QObject *parent = 0); 45 | virtual ~Timer(); 46 | 47 | bool isSingleShot() const; 48 | void setSingleShot(bool singleShot); 49 | int interval() const; 50 | void setInterval(int msec); 51 | void start(); 52 | void stop(); 53 | 54 | protected: 55 | QTimer _timer; 56 | }; 57 | 58 | } 59 | 60 | #endif // QMQTT_TIMER_H 61 | -------------------------------------------------------------------------------- /libqmqtt/qmqtt_timerinterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * qmqtt_timerinterface.h - qmqtt timer interface header 3 | * 4 | * Copyright (c) 2013 Ery Lee 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of mqttc nor the names of its contributors may be used 16 | * to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #ifndef QMQTT_TIMER_INTERFACE_H 33 | #define QMQTT_TIMER_INTERFACE_H 34 | 35 | #include 36 | 37 | namespace QMQTT { 38 | 39 | class TimerInterface : public QObject 40 | { 41 | Q_OBJECT 42 | public: 43 | explicit TimerInterface(QObject* parent = NULL) : QObject(parent) {} 44 | virtual ~TimerInterface() {} 45 | 46 | virtual bool isSingleShot() const = 0; 47 | virtual void setSingleShot(bool singleShot) = 0; 48 | virtual int interval() const = 0; 49 | virtual void setInterval(int msec) = 0; 50 | virtual void start() = 0; 51 | virtual void stop() = 0; 52 | 53 | signals: 54 | void timeout(); 55 | }; 56 | 57 | } 58 | 59 | #endif // QMQTT_TIMER_INTERFACE_H 60 | 61 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2021 Jakob Flierl 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of mqttc nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #include 32 | 33 | #include "mainwindow.h" 34 | 35 | int main(int argc, char** argv) 36 | { 37 | QApplication app(argc, argv); 38 | 39 | MainWindow w; 40 | w.show(); 41 | 42 | return app.exec(); 43 | } 44 | -------------------------------------------------------------------------------- /main.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | TARGET = qmqtt-plot 4 | 5 | DEFINES += QMQTT_EXAMPLE 6 | 7 | INCLUDEPATH += libqmqtt 8 | 9 | SOURCES = main.cpp \ 10 | mainwindow.cpp ledindicator.cpp qcustomplot.cpp \ 11 | \ 12 | libqmqtt/qmqtt_client.cpp libqmqtt/qmqtt_network.cpp libqmqtt/qmqtt_ssl_network.cpp \ 13 | libqmqtt/qmqtt_client_p.cpp libqmqtt/qmqtt_routedmessage.cpp libqmqtt/qmqtt_ssl_socket.cpp \ 14 | libqmqtt/qmqtt_frame.cpp libqmqtt/qmqtt_router.cpp libqmqtt/qmqtt_timer.cpp \ 15 | libqmqtt/qmqtt_message.cpp libqmqtt/qmqtt_routesubscription.cpp \ 16 | libqmqtt/qmqtt_message_p.cpp libqmqtt/qmqtt_socket.cpp \ 17 | 18 | FORMS += \ 19 | mainwindow.ui 20 | 21 | HEADERS += \ 22 | mainwindow.h ledindicator.h qcustomplot.h \ 23 | \ 24 | libqmqtt/qmqtt_client.h libqmqtt/qmqtt_message_p.h libqmqtt/qmqtt_socket.h \ 25 | libqmqtt/qmqtt_client_p.h libqmqtt/qmqtt_network.h libqmqtt/qmqtt_socketinterface.h \ 26 | libqmqtt/qmqtt_frame.h libqmqtt/qmqtt_networkinterface.h libqmqtt/qmqtt_ssl_network.h \ 27 | libqmqtt/qmqtt_global.h libqmqtt/qmqtt_routedmessage.h libqmqtt/qmqtt_ssl_socket.h \ 28 | libqmqtt/qmqtt.h libqmqtt/qmqtt_router.h libqmqtt/qmqtt_timer.h \ 29 | libqmqtt/qmqtt_message.h libqmqtt/qmqtt_routesubscription.h libqmqtt/qmqtt_timerinterface.h \ 30 | 31 | win32 { 32 | 33 | } else { 34 | MOC_DIR = .moc 35 | #OBJECTS_DIR = .obj 36 | UI_DIR = .ui 37 | RCC_DIR = .rcc 38 | 39 | CONFIG += link_pkgconfig 40 | 41 | qmqtt-plot-binary.path = /usr/bin 42 | qmqtt-plot-binary.files = qmqtt-plot 43 | qmqtt-plot-deskop.path = /usr/share/applications 44 | qmqtt-plot-deskop.files = qmqtt-plot.desktop 45 | qmqtt-plot-icons.path = /usr/share/icons/hicolor/scalable/apps 46 | qmqtt-plot-icons.files = qmqtt-plot.svg 47 | 48 | INSTALLS += qmqtt-plot-binary qmqtt-plot-deskop qmqtt-plot-icons 49 | 50 | RESOURCES += res.qrc 51 | } 52 | 53 | win32 { 54 | DEFINES += BUILDTIME=\\\"HH:MM\\\" 55 | DEFINES += BUILDDATE=\\\"Y-m-d\\\" 56 | } else { 57 | DEFINES += BUILDTIME=\\\"$$system(date '+%H:%M')\\\" 58 | DEFINES += BUILDDATE=\\\"$$system(date '+%Y-%m-%d')\\\" 59 | } 60 | 61 | QMAKE_CXXFLAGS_RELEASE += -O2 62 | QMAKE_CXXFLAGS_DEBUG += -O0 63 | 64 | CONFIG *= debug_and_release 65 | CONFIG *= qt 66 | CONFIG += warn_on 67 | CONFIG += thread 68 | CONFIG += c++11 69 | 70 | QT += core network gui printsupport widgets 71 | 72 | ICON = qmqtt-plot.svg 73 | 74 | OTHER_FILES += README.md qmqtt-plot.svg qmqtt-plot.desktop 75 | 76 | DIRS_DC = object_script.* .ui .moc .rcc .obj *.pro.user $$TARGET 77 | 78 | unix:QMAKE_DISTCLEAN += -r $$DIRS_DC 79 | win32:QMAKE_DISTCLEAN += /s /f /q $$DIRS_DC && rd /s /q $$DIRS_DC 80 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2021 Jakob Flierl 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of mqttc nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "mainwindow.h" 38 | #include "ui_mainwindow.h" 39 | 40 | MainWindow::MainWindow(QWidget *parent) : 41 | QMainWindow(parent), 42 | ui(new Ui::MainWindow) 43 | { 44 | ui->setupUi(this); 45 | 46 | zoomTime = 1; 47 | 48 | ui->log->setMaximumBlockCount(100); 49 | 50 | QList s; // exit app with ESC or CTRL+Q 51 | s << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::CTRL + Qt::Key_Q); 52 | ui->action_Quit->setShortcuts(s); 53 | 54 | mqttHost = new QLineEdit(); 55 | mqttHost->setMaximumWidth(200); 56 | 57 | ui->toolBar->insertWidget(ui->actionConnect_Disconnect, mqttHost); 58 | 59 | mqttTopic = new QLineEdit(); 60 | mqttTopic->setMaximumWidth(200); 61 | 62 | ui->toolBar->insertWidget(ui->actionConnect_Disconnect, mqttTopic); 63 | 64 | led1 = new QLedIndicator(this); 65 | led1->setOn(true); 66 | 67 | lag = new QLabel(); 68 | lag->setMinimumWidth(150); 69 | lag->setAlignment(Qt::AlignRight); 70 | 71 | ui->status->addWidget(led1); 72 | ui->statusbar->addWidget(lag, 0); 73 | 74 | for (int i = 0; i < 5; i++) { 75 | ui->plot->addGraph(); 76 | ui->plot->legend->setVisible(true); 77 | 78 | //ui->plot->graph(i)->setAntialiased(false); 79 | ui->plot->graph(i)->setAntialiased(true); 80 | 81 | //ui->plot->graph(i)->setLineStyle(QCPGraph::lsNone); 82 | //ui->plot->graph(i)->setLineStyle(QCPGraph::lsStepLeft); 83 | ui->plot->graph(i)->setLineStyle(QCPGraph::lsLine); 84 | QPen pen(Qt::black); 85 | pen.setWidth(2); 86 | pen.setColor(QColor(0,0,0,0x7f)); 87 | ui->plot->graph(i)->setPen(pen); 88 | ui->plot->graph(i)->setName(QString("J%1").arg(i+1)); 89 | 90 | QCPScatterStyle myScatter; 91 | myScatter.setShape(QCPScatterStyle::ssCircle); 92 | switch(i) { 93 | case 0: 94 | myScatter.setPen(QPen(Qt::red)); 95 | break; 96 | case 1: 97 | myScatter.setPen(QPen(Qt::green)); 98 | break; 99 | case 2: 100 | myScatter.setPen(QPen(Qt::blue)); 101 | break; 102 | case 3: 103 | myScatter.setPen(QPen(Qt::yellow)); 104 | break; 105 | case 4: 106 | myScatter.setPen(QPen(Qt::darkYellow)); 107 | break; 108 | } 109 | myScatter.setBrush(Qt::black); 110 | myScatter.setSize(3); 111 | ui->plot->graph(i)->setScatterStyle(myScatter); 112 | } 113 | 114 | ui->plot->xAxis->setRange(0,10); 115 | ui->plot->yAxis->setRange(-0.25,1.25); 116 | ui->plot->yAxis->setAutoTickStep(true); 117 | ui->plot->yAxis->setAutoTickCount(7); 118 | 119 | ui->plot->xAxis->setDateTimeFormat("h:mm:ss"); 120 | ui->plot->xAxis->setTickLabelType(QCPAxis::ltDateTime); 121 | ui->plot->xAxis->setAutoTickStep(true); 122 | ui->plot->xAxis->setTickStep(1); 123 | 124 | ui->plot->yAxis->rescale(true); 125 | ui->plot->rescaleAxes(); 126 | 127 | ui->plot->axisRect()->setupFullAxesBox(true); 128 | 129 | ui->plot->replot(); 130 | 131 | ui->tabWidget->setTabText(0, tr("Plot")); 132 | ui->tabWidget->setTabText(1, tr("Log")); 133 | ui->tabWidget->setCurrentIndex(0); 134 | 135 | settings = new QSettings(); 136 | 137 | subscriber = new Subscriber(QHostAddress(EXAMPLE_HOST), 138 | EXAMPLE_PORT, this); 139 | 140 | //Publisher publisher; 141 | //publisher.connectToHost(); 142 | 143 | timer = new QTimer(this); 144 | timer->setSingleShot(false); 145 | 146 | connect(timer, SIGNAL(timeout()), this, SLOT(updatePlot())); 147 | 148 | connect(subscriber, SIGNAL(signalReceived(QString, QString)), this, SLOT(onReceived(QString, QString))); 149 | 150 | connect(subscriber, SIGNAL(connected()), this, SLOT(onConnected())); 151 | connect(subscriber, SIGNAL(disconnected()), this, SLOT(onDisconnected())); 152 | 153 | connect(ui->actionConnect_Disconnect, SIGNAL(toggled(bool)), this, SLOT(connectDisconnectMQTT(bool))); 154 | connect(mqttTopic, SIGNAL(textChanged(QString)), this, SLOT(updateMQTTSubscription())); 155 | 156 | loadSettings(); 157 | 158 | timer->start(1000/120); // fps 159 | } 160 | 161 | void MainWindow::on_action_Zoom_In_triggered() { 162 | zoomTime /= 2; 163 | if (zoomTime > 60) { 164 | ui->plot->xAxis->setTickStep(60); 165 | ui->plot->xAxis->setDateTimeFormat("h:mm"); 166 | } else if (zoomTime > 1) { 167 | ui->plot->xAxis->setTickStep(1); 168 | ui->plot->xAxis->setDateTimeFormat("h:mm:ss"); 169 | } else { 170 | ui->plot->xAxis->setDateTimeFormat("h:mm:ss:zzz"); 171 | ui->plot->xAxis->setTickStep(0.1); 172 | } 173 | } 174 | 175 | void MainWindow::on_action_Zoom_Out_triggered() { 176 | zoomTime *= 2; 177 | if (zoomTime > 60) { 178 | ui->plot->xAxis->setTickStep(60); 179 | ui->plot->xAxis->setDateTimeFormat("h:mm"); 180 | } else if (zoomTime > 1) { 181 | ui->plot->xAxis->setTickStep(1); 182 | ui->plot->xAxis->setDateTimeFormat("h:mm:ss"); 183 | } else { 184 | ui->plot->xAxis->setDateTimeFormat("h:mm:ss:zzz"); 185 | ui->plot->xAxis->setTickStep(0.1); 186 | } 187 | } 188 | 189 | void MainWindow::connectDisconnectMQTT(bool connect) { 190 | if (connect) { 191 | if (!subscriber->connectionState()) { 192 | led1->setDisconnected(true); 193 | subscriber->setHostName(mqttHost->text()); 194 | subscriber->connectToHost(); 195 | subscriber->setAutoReconnect(true); 196 | ui->statusbar->showMessage(tr("Connecting to %1").arg(mqttHost->text())); 197 | } 198 | } else { 199 | subscriber->setAutoReconnect(false); 200 | subscriber->disconnectFromHost(); 201 | subscriber->cleanSession(); 202 | led1->setDisconnected(true); 203 | } 204 | } 205 | 206 | void MainWindow::updateMQTTSubscription() { 207 | if (!mqttTopicOld.isEmpty()) { 208 | subscriber->unsubscribe(mqttTopicOld); 209 | } 210 | 211 | subscriber->subscribe(mqttTopic->text(), 0); 212 | 213 | mqttTopicOld = mqttTopic->text(); 214 | } 215 | 216 | void MainWindow::onConnected() { 217 | ui->statusbar->showMessage(tr("Connected to %1").arg(subscriber->hostName()), 1000); 218 | log(QString("connected to %1").arg(subscriber->hostName())); 219 | led1->setDisconnected(false); 220 | ui->actionConnect_Disconnect->setChecked(true); 221 | ui->actionConnect_Disconnect->setToolTip(tr("Disconnect")); 222 | 223 | updateMQTTSubscription(); 224 | } 225 | 226 | void MainWindow::onDisconnected() { 227 | ui->statusbar->showMessage(tr("Disconnected"), 1000); 228 | log("disconnected"); 229 | led1->setDisconnected(true); 230 | ui->actionConnect_Disconnect->setChecked(false); 231 | ui->actionConnect_Disconnect->setToolTip(tr("Connect")); 232 | } 233 | 234 | void MainWindow::onReceived(QString topic, QString msg) { 235 | double tsl = QDateTime::currentMSecsSinceEpoch() / 1000.0; 236 | 237 | log(QString("%1: %2").arg(topic, msg)); 238 | 239 | bool ok_ts, ok[6]; 240 | double ts = msg.split(" ")[0].toDouble(&ok_ts); 241 | double val[6]; 242 | 243 | for (int i = 1; i < 6; i++) { 244 | val[i-1] = msg.split(" ")[i].toDouble(&ok[i-1]); 245 | } 246 | 247 | if (ok_ts && ok[0] && ok[1] && ok[2] && ok[3] && ok[4]) { 248 | //led1->setOn(val[0]); 249 | 250 | for (int i = 0; i < 5; i++) { 251 | ui->plot->graph(i)->addData(ts, val[i]); 252 | ui->plot->graph(i)->removeDataBefore(ts - qMin((int)(zoomTime*10), 600)); // max 10 minutes buffer size 253 | } 254 | // ui->plot->graph(0)->setName(topic); 255 | 256 | double lagt = (tsl - ts) * 1000; 257 | lag->setText(tr("%1%2 msec lag").arg(lagt < 0 ? '-' : ' ').arg(qFabs(lagt),5,'f',2,' ')); 258 | 259 | } else { 260 | QString info; 261 | info = QString("%1 %2 %3 %4").arg(QString::number(ts, 'f'), 262 | QString::number(val[0]), 263 | QString::number(ok_ts), 264 | QString::number(ok[0])); 265 | 266 | log(tr("%1: error while converting %1").arg(topic, info)); 267 | } 268 | } 269 | 270 | void MainWindow::loadSettings() { 271 | settings->beginGroup("gui"); 272 | 273 | restoreGeometry(settings->value("geometry", saveGeometry() ).toByteArray()); 274 | restoreState(settings->value("state", saveState() ).toByteArray()); 275 | move(settings->value("pos", pos()).toPoint()); 276 | resize(settings->value("size", size()).toSize()); 277 | 278 | if ( settings->value("fullscreen", isFullScreen() ).toBool()) { 279 | showFullScreen(); 280 | } else { 281 | showNormal(); 282 | } 283 | if ( settings->value("maximized", isMaximized() ).toBool()) { 284 | showMaximized(); 285 | } 286 | 287 | zoomTime = settings->value("zoomTime", 1).toDouble(); 288 | 289 | settings->endGroup(); 290 | 291 | settings->beginGroup("mqtt"); 292 | mqttHost->setText(settings->value("host", "127.0.0.1").toString()); 293 | mqttTopic->setText(settings->value("topic", "Robot/Coordinates").toString()); 294 | settings->endGroup(); 295 | } 296 | 297 | void MainWindow::saveSettings() { 298 | settings->beginGroup("gui"); 299 | 300 | settings->setValue("geometry", saveGeometry()); 301 | settings->setValue("state", saveState()); 302 | settings->setValue("fullscreen", isFullScreen()); 303 | settings->setValue("maximized", isMaximized()); 304 | 305 | if ( !isMaximized() && !isFullScreen() ) { 306 | settings->setValue("pos", pos()); 307 | settings->setValue("size", size()); 308 | } 309 | 310 | settings->setValue("zoomTime", zoomTime); 311 | 312 | settings->endGroup(); 313 | 314 | settings->beginGroup("mqtt"); 315 | settings->setValue("host", mqttHost->text()); 316 | settings->setValue("topic", mqttTopic->text()); 317 | settings->endGroup(); 318 | } 319 | 320 | void MainWindow::closeEvent(QCloseEvent * event) { 321 | saveSettings(); 322 | event->accept(); 323 | } 324 | 325 | void MainWindow::keyPressEvent(QKeyEvent *e) { 326 | int keyInt = e->key(); 327 | Qt::Key key = static_cast(keyInt); 328 | 329 | if (key == Qt::Key_unknown) { 330 | log(tr("Unknown key from a macro probably.")); 331 | return; 332 | } 333 | // the user have clicked just and only the special keys Ctrl, Shift, Alt, Meta. 334 | if (key == Qt::Key_Control || 335 | key == Qt::Key_Shift || 336 | key == Qt::Key_Alt || 337 | key == Qt::Key_Meta) 338 | { 339 | // qDebug() << "Single click of special key: Ctrl, Shift, Alt or Meta"; 340 | // qDebug() << "New KeySequence:" << QKeySequence(keyInt).toString(QKeySequence::NativeText); 341 | // return; 342 | } 343 | 344 | // check for a combination of user clicks 345 | Qt::KeyboardModifiers modifiers = e->modifiers(); 346 | QString keyText = e->text(); 347 | // if the keyText is empty than it's a special key like F1, F5, ... 348 | // qDebug() << "Pressed Key:" << keyText; 349 | QList modifiersList; 350 | if (modifiers & Qt::ShiftModifier) 351 | keyInt += Qt::SHIFT; 352 | if (modifiers & Qt::ControlModifier) 353 | keyInt += Qt::CTRL; 354 | if (modifiers & Qt::AltModifier) 355 | keyInt += Qt::ALT; 356 | if (modifiers & Qt::MetaModifier) 357 | keyInt += Qt::META; 358 | 359 | QString seq = QKeySequence(keyInt).toString(QKeySequence::NativeText); 360 | // qDebug() << "KeySequence:" << seq; 361 | 362 | return; // skip built in command if overridden by shortcut 363 | QMainWindow::keyPressEvent(e); 364 | } 365 | 366 | void MainWindow::log(QString l) { 367 | QString ts; 368 | ts.sprintf("%06.5f", QDateTime::currentMSecsSinceEpoch() / 1000.0); 369 | ui->log->appendPlainText(QString("%1 %2").arg(ts, l)); 370 | } 371 | 372 | void MainWindow::updatePlot() { 373 | double tsl = QDateTime::currentMSecsSinceEpoch() / 1000.0; 374 | ui->plot->xAxis->setRange(tsl - zoomTime, tsl); 375 | ui->plot->yAxis->rescale(true); 376 | //ui->plot->rescaleAxes(); 377 | ui->plot->replot(QCustomPlot::rpQueued); 378 | } 379 | 380 | void MainWindow::on_action_Print_triggered() { 381 | QPrinter printer; 382 | printer.setPageMargins (15,15,15,15, QPrinter::Millimeter); 383 | printer.setPageSize(QPrinter::A4); 384 | printer.setOrientation(QPrinter::Landscape); 385 | //printer.setResolution(QPrinter::HighResolution); 386 | printer.setFullPage(false); 387 | 388 | QPrintPreviewDialog preview(&printer, this); 389 | preview.setWindowTitle("Preview Dialog"); 390 | Qt::WindowFlags flags(Qt::WindowTitleHint | Qt::Window); 391 | preview.setWindowFlags(flags); 392 | connect(&preview, SIGNAL(paintRequested(QPrinter *)), SLOT(printPreview(QPrinter *))); 393 | preview.exec(); 394 | } 395 | 396 | void MainWindow::printPreview(QPrinter *printer) { 397 | printer->setPageSize(QPrinter::A4); 398 | QCPPainter painter(printer); 399 | QRectF pageRect = printer->pageRect(QPrinter::DevicePixel); 400 | 401 | int plotWidth = ui->plot->viewport().width(); 402 | int plotHeight = ui->plot->viewport().height(); 403 | double scale = qMin(pageRect.width()/(double)plotWidth, pageRect.height()/(double)plotHeight); 404 | 405 | painter.setRenderHints(QPainter::Antialiasing | 406 | QPainter::TextAntialiasing | 407 | QPainter::SmoothPixmapTransform, true); 408 | 409 | painter.setMode(QCPPainter::pmVectorized); 410 | painter.setMode(QCPPainter::pmNoCaching); 411 | 412 | // comment this out if you want cosmetic thin lines (always 1 pixel thick independent of pdf zoom level) 413 | painter.setMode(QCPPainter::pmNonCosmetic); 414 | 415 | painter.scale(scale, scale); 416 | ui->plot->toPainter(&painter, plotWidth, plotHeight); 417 | } 418 | 419 | MainWindow::~MainWindow() 420 | { 421 | delete ui; 422 | } 423 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Jakob Flierl 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of mqttc nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #ifndef MAINWINDOW_H 32 | #define MAINWINDOW_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "ledindicator.h" 44 | 45 | const QHostAddress EXAMPLE_HOST = QHostAddress("192.168.0.114"); 46 | const quint16 EXAMPLE_PORT = 1883; 47 | const QString EXAMPLE_TOPIC = "rm501/0/pos"; 48 | 49 | class Publisher : public QMQTT::Client 50 | { 51 | Q_OBJECT 52 | public: 53 | explicit Publisher(const QHostAddress& host = EXAMPLE_HOST, 54 | const quint16 port = EXAMPLE_PORT, 55 | QObject* parent = NULL) 56 | : QMQTT::Client(host, port, parent) 57 | , _number(0) 58 | { 59 | connect(this, &Publisher::connected, this, &Publisher::onConnected); 60 | connect(&_timer, &QTimer::timeout, this, &Publisher::onTimeout); 61 | connect(this, &Publisher::disconnected, this, &Publisher::onDisconnected); 62 | } 63 | virtual ~Publisher() {} 64 | 65 | QTimer _timer; 66 | quint16 _number; 67 | 68 | public slots: 69 | void onConnected() 70 | { 71 | subscribe(EXAMPLE_TOPIC, 0); 72 | _timer.start(1000); 73 | } 74 | 75 | void onTimeout() 76 | { 77 | QMQTT::Message message(_number, EXAMPLE_TOPIC, 78 | QString("Number is %1").arg(_number).toUtf8()); 79 | publish(message); 80 | _number++; 81 | if(_number >= 10) 82 | { 83 | _timer.stop(); 84 | disconnectFromHost(); 85 | } 86 | } 87 | 88 | void onDisconnected() 89 | { 90 | #if (QT_VERSION < QT_VERSION_CHECK(5, 4, 0)) 91 | QTimer::singleShot(0, qApp, SLOT(QCoreApplication::quit())); 92 | #else 93 | QTimer::singleShot(0, qApp, &QCoreApplication::quit); 94 | #endif 95 | } 96 | }; 97 | 98 | class Subscriber : public QMQTT::Client 99 | { 100 | Q_OBJECT 101 | public: 102 | explicit Subscriber(const QHostAddress& host = EXAMPLE_HOST, 103 | const quint16 port = EXAMPLE_PORT, 104 | QObject* parent = NULL) 105 | : QMQTT::Client(host, port, parent) 106 | , _qout(stdout) 107 | { 108 | connect(this, &Subscriber::connected, this, &Subscriber::onConnected); 109 | connect(this, &Subscriber::disconnected, this, &Subscriber::onDisconnected); 110 | connect(this, &Subscriber::subscribed, this, &Subscriber::onSubscribed); 111 | connect(this, &Subscriber::received, this, &Subscriber::onReceived); 112 | } 113 | virtual ~Subscriber() {} 114 | 115 | QTextStream _qout; 116 | 117 | signals: 118 | void signalReceived(QString topic, QString msg); 119 | void signalConnected(); 120 | void signalDisconnected(); 121 | void signalSubscribed(QString topic); 122 | 123 | public slots: 124 | void onConnected() 125 | { 126 | // _qout << "connected" << endl; 127 | emit signalConnected(); 128 | } 129 | 130 | void onDisconnected() 131 | { 132 | // _qout << "disconnected" << endl; 133 | emit signalDisconnected(); 134 | } 135 | 136 | void onSubscribed(const QString& topic) 137 | { 138 | Q_UNUSED(topic) 139 | // _qout << "subscribed " << topic << endl; 140 | emit signalSubscribed(topic); 141 | } 142 | 143 | void onReceived(const QMQTT::Message& message) 144 | { 145 | emit signalReceived(message.topic(), QString::fromUtf8(message.payload())); 146 | // _qout << "publish received: \"" << QString::fromUtf8(message.payload()) 147 | // << "\"" << endl; 148 | } 149 | }; 150 | 151 | namespace Ui { 152 | class MainWindow; 153 | } 154 | 155 | class MainWindow : public QMainWindow 156 | { 157 | Q_OBJECT 158 | 159 | public: 160 | explicit MainWindow(QWidget *parent = 0); 161 | ~MainWindow(); 162 | 163 | public slots: 164 | void onReceived(QString topic, QString msg); 165 | 166 | void onConnected(); 167 | void onDisconnected(); 168 | 169 | void connectDisconnectMQTT(bool connect); 170 | 171 | void keyPressEvent(QKeyEvent *e); 172 | 173 | void loadSettings(); 174 | void saveSettings(); 175 | 176 | void log(QString l); 177 | 178 | void on_action_Zoom_In_triggered(); 179 | void on_action_Zoom_Out_triggered(); 180 | 181 | void on_action_Print_triggered(); 182 | 183 | void printPreview(QPrinter *printer); 184 | 185 | void updateMQTTSubscription(); 186 | 187 | private slots: 188 | void closeEvent(QCloseEvent *); 189 | void updatePlot(); 190 | 191 | private: 192 | Ui::MainWindow *ui; 193 | 194 | Subscriber *subscriber; 195 | 196 | QSettings *settings; 197 | QLineEdit *mqttHost; 198 | QLineEdit *mqttTopic; 199 | 200 | QLedIndicator *led1; 201 | 202 | QTimer *timer; 203 | 204 | QLabel *lag; 205 | 206 | double zoomTime; 207 | 208 | QString mqttTopicOld; 209 | }; 210 | 211 | #endif // MAINWINDOW_H 212 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 651 10 | 474 11 | 12 | 13 | 14 | qmqtt-plot 15 | 16 | 17 | 18 | :/qmqtt-plot.svg:/qmqtt-plot.svg 19 | 20 | 21 | 22 | 23 | 6 24 | 25 | 26 | 6 27 | 28 | 29 | 6 30 | 31 | 32 | 6 33 | 34 | 35 | 36 | 37 | 0 38 | 39 | 40 | 41 | Tab 1 42 | 43 | 44 | 45 | 6 46 | 47 | 48 | 6 49 | 50 | 51 | 6 52 | 53 | 54 | 6 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Tab 2 64 | 65 | 66 | 67 | 6 68 | 69 | 70 | 6 71 | 72 | 73 | 6 74 | 75 | 76 | 6 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 0 91 | 0 92 | 651 93 | 25 94 | 95 | 96 | 97 | 98 | 99 | 100 | toolBar 101 | 102 | 103 | TopToolBarArea 104 | 105 | 106 | false 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | toolBar_2 115 | 116 | 117 | TopToolBarArea 118 | 119 | 120 | false 121 | 122 | 123 | 124 | 125 | toolBar_2 126 | 127 | 128 | TopToolBarArea 129 | 130 | 131 | false 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | true 141 | 142 | 143 | 144 | .. 145 | 146 | 147 | Connect / Disconnect 148 | 149 | 150 | Connect 151 | 152 | 153 | Space 154 | 155 | 156 | 157 | 158 | 159 | .. 160 | 161 | 162 | Quit 163 | 164 | 165 | 166 | 167 | 168 | .. 169 | 170 | 171 | Zoom In 172 | 173 | 174 | Zoom In Time 175 | 176 | 177 | Ctrl++ 178 | 179 | 180 | 181 | 182 | 183 | .. 184 | 185 | 186 | Zoom Out 187 | 188 | 189 | Zoom Out Time 190 | 191 | 192 | Ctrl+- 193 | 194 | 195 | 196 | 197 | 198 | .. 199 | 200 | 201 | Print 202 | 203 | 204 | Ctrl+P 205 | 206 | 207 | 208 | 209 | 210 | QCustomPlot 211 | QWidget 212 |
qcustomplot.h
213 | 1 214 |
215 |
216 | 217 | 218 | 219 | 220 | 221 | action_Quit 222 | triggered() 223 | MainWindow 224 | close() 225 | 226 | 227 | -1 228 | -1 229 | 230 | 231 | 139 232 | 152 233 | 234 | 235 | 236 | 237 |
238 | -------------------------------------------------------------------------------- /qmqtt-plot.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Version=1.0 4 | Name=qmqtt-plot 5 | GenericName=QMQTT Plot 6 | Comment=MQTT Timestamped data plotter 7 | Icon=/usr/share/icons/hicolor/scalable/apps/qmqtt-plot.svg 8 | 9 | Type=Application 10 | Categories=Engineering;Development 11 | 12 | Exec=qmqtt-plot %f 13 | Terminal=false 14 | -------------------------------------------------------------------------------- /qmqtt-plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/koppi/qmqtt-plot/153e953da56d987215f4dc3e9ffb7b01d5994ac6/qmqtt-plot.png -------------------------------------------------------------------------------- /qmqtt-plot.svg: -------------------------------------------------------------------------------- 1 | 2 | 22 | 38 | 44 | 49 | 55 | 61 | 65 | 70 | 75 | 77 | 82 | 84 | 86 | 88 | image/svg+xml 91 | 94 | 97 | 99 | 102 | Openclipart 105 | 107 | 109 | 111 | 114 | 117 | 120 | 123 | 125 | 127 | 129 | 131 | -------------------------------------------------------------------------------- /res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | qmqtt-plot.svg 6 | 7 | 8 | --------------------------------------------------------------------------------