├── .abapgit.xml ├── LICENSE ├── README.md ├── abaplint.json └── src ├── mqtt ├── package.devc.xml ├── packets │ ├── package.devc.xml │ ├── zcl_mqtt_packet_connack.clas.abap │ ├── zcl_mqtt_packet_connack.clas.testclasses.abap │ ├── zcl_mqtt_packet_connack.clas.xml │ ├── zcl_mqtt_packet_connect.clas.abap │ ├── zcl_mqtt_packet_connect.clas.testclasses.abap │ ├── zcl_mqtt_packet_connect.clas.xml │ ├── zcl_mqtt_packet_disconnect.clas.abap │ ├── zcl_mqtt_packet_disconnect.clas.testclasses.abap │ ├── zcl_mqtt_packet_disconnect.clas.xml │ ├── zcl_mqtt_packet_pingreq.clas.abap │ ├── zcl_mqtt_packet_pingreq.clas.testclasses.abap │ ├── zcl_mqtt_packet_pingreq.clas.xml │ ├── zcl_mqtt_packet_pingresp.clas.abap │ ├── zcl_mqtt_packet_pingresp.clas.testclasses.abap │ ├── zcl_mqtt_packet_pingresp.clas.xml │ ├── zcl_mqtt_packet_puback.clas.abap │ ├── zcl_mqtt_packet_puback.clas.testclasses.abap │ ├── zcl_mqtt_packet_puback.clas.xml │ ├── zcl_mqtt_packet_pubcomp.clas.abap │ ├── zcl_mqtt_packet_pubcomp.clas.testclasses.abap │ ├── zcl_mqtt_packet_pubcomp.clas.xml │ ├── zcl_mqtt_packet_publish.clas.abap │ ├── zcl_mqtt_packet_publish.clas.testclasses.abap │ ├── zcl_mqtt_packet_publish.clas.xml │ ├── zcl_mqtt_packet_pubrec.clas.abap │ ├── zcl_mqtt_packet_pubrec.clas.testclasses.abap │ ├── zcl_mqtt_packet_pubrec.clas.xml │ ├── zcl_mqtt_packet_pubrel.clas.abap │ ├── zcl_mqtt_packet_pubrel.clas.testclasses.abap │ ├── zcl_mqtt_packet_pubrel.clas.xml │ ├── zcl_mqtt_packet_suback.clas.abap │ ├── zcl_mqtt_packet_suback.clas.testclasses.abap │ ├── zcl_mqtt_packet_suback.clas.xml │ ├── zcl_mqtt_packet_subscribe.clas.abap │ ├── zcl_mqtt_packet_subscribe.clas.testclasses.abap │ ├── zcl_mqtt_packet_subscribe.clas.xml │ ├── zcl_mqtt_packet_unsuback.clas.abap │ ├── zcl_mqtt_packet_unsuback.clas.testclasses.abap │ ├── zcl_mqtt_packet_unsuback.clas.xml │ ├── zcl_mqtt_packet_unsubscribe.clas.abap │ ├── zcl_mqtt_packet_unsubscribe.clas.testclasses.abap │ ├── zcl_mqtt_packet_unsubscribe.clas.xml │ ├── zcl_mqtt_stream.clas.abap │ ├── zcl_mqtt_stream.clas.testclasses.abap │ ├── zcl_mqtt_stream.clas.xml │ ├── zif_mqtt_packet.intf.abap │ └── zif_mqtt_packet.intf.xml ├── zcl_mqtt_transport_tcp.clas.abap ├── zcl_mqtt_transport_tcp.clas.xml ├── zcl_mqtt_transport_ws.clas.abap ├── zcl_mqtt_transport_ws.clas.xml ├── zcx_mqtt.clas.abap ├── zcx_mqtt.clas.xml ├── zcx_mqtt_timeout.clas.abap ├── zcx_mqtt_timeout.clas.xml ├── zif_mqtt_constants.intf.abap ├── zif_mqtt_constants.intf.xml ├── zif_mqtt_transport.intf.abap └── zif_mqtt_transport.intf.xml ├── package.devc.xml └── test ├── package.devc.xml ├── zabapmq_http_client.prog.abap ├── zabapmq_http_client.prog.xml ├── zabapmq_mqtt.prog.abap ├── zabapmq_mqtt.prog.xml ├── zabapmq_performance.prog.abap └── zabapmq_performance.prog.xml /.abapgit.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | E 6 | /src/ 7 | PREFIX 8 | 9 | /.gitignore 10 | /LICENSE 11 | /README.md 12 | /package.json 13 | /.travis.yml 14 | 15 | 16 | 17 | SAP_BASIS 18 | 750 19 | 0001 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 INVIXO Consulting Group A/S 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # abapMQ 2 | 3 | MQTT client implemented in ABAP 4 | 5 | Supports: 6 | * [MQTT, Version 3.1.1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html) 7 | 8 | ABAP version 750sp01 required 9 | 10 | Install via [abapGit](http://abapgit.org) 11 | -------------------------------------------------------------------------------- /abaplint.json: -------------------------------------------------------------------------------- 1 | { 2 | "global": { 3 | "files": "/src/**/*.*", 4 | "skipGeneratedGatewayClasses": true, 5 | "skipGeneratedPersistentClasses": true, 6 | "skipGeneratedFunctionGroups": true, 7 | "applyUnspecifiedRules": false 8 | }, 9 | "dependencies": [ 10 | { 11 | "url": "https://github.com/abaplint/deps", 12 | "folder": "/deps", 13 | "files": "/src/**/*.*" 14 | } 15 | ], 16 | "syntax": { 17 | "version": "v750", 18 | "errorNamespace": "^(Z|Y)", 19 | "globalConstants": [], 20 | "globalMacros": [] 21 | }, 22 | "rules": { 23 | "7bit_ascii": { 24 | "enabled": true, 25 | "exclude": [], 26 | "reason": "" 27 | }, 28 | "abapdoc": { 29 | "enabled": false, 30 | "exclude": [], 31 | "reason": "", 32 | "checkLocal": false 33 | }, 34 | "allowed_object_naming": { 35 | "enabled": true, 36 | "exclude": [], 37 | "reason": "" 38 | }, 39 | "allowed_object_types": { 40 | "enabled": true, 41 | "exclude": [], 42 | "reason": "", 43 | "allowed": [] 44 | }, 45 | "ambiguous_statement": { 46 | "enabled": true, 47 | "exclude": [], 48 | "reason": "" 49 | }, 50 | "avoid_use": { 51 | "enabled": true, 52 | "exclude": [], 53 | "reason": "", 54 | "define": true, 55 | "endselect": true, 56 | "execSQL": true, 57 | "kernelCall": true, 58 | "communication": true, 59 | "statics": true, 60 | "systemCall": true 61 | }, 62 | "begin_end_names": { 63 | "enabled": true, 64 | "exclude": [], 65 | "reason": "" 66 | }, 67 | "breakpoint": { 68 | "enabled": true, 69 | "exclude": [], 70 | "reason": "" 71 | }, 72 | "chain_mainly_declarations": { 73 | "enabled": true, 74 | "exclude": [], 75 | "reason": "" 76 | }, 77 | "check_abstract": { 78 | "enabled": true, 79 | "exclude": [], 80 | "reason": "" 81 | }, 82 | "check_comments": { 83 | "enabled": false, 84 | "exclude": [], 85 | "reason": "", 86 | "allowEndOfLine": false 87 | }, 88 | "check_ddic": { 89 | "enabled": true, 90 | "exclude": [], 91 | "reason": "" 92 | }, 93 | "check_include": { 94 | "enabled": true, 95 | "exclude": [], 96 | "reason": "" 97 | }, 98 | "check_no_handler_pragma": { 99 | "enabled": true, 100 | "exclude": [], 101 | "reason": "" 102 | }, 103 | "check_syntax": { 104 | "enabled": true, 105 | "exclude": [], 106 | "reason": "" 107 | }, 108 | "check_text_elements": { 109 | "enabled": true, 110 | "exclude": [], 111 | "reason": "" 112 | }, 113 | "check_transformation_exists": { 114 | "enabled": true, 115 | "exclude": [], 116 | "reason": "" 117 | }, 118 | "class_attribute_names": { 119 | "enabled": false, 120 | "exclude": [], 121 | "reason": "", 122 | "patternKind": "required", 123 | "ignoreNames": [], 124 | "ignorePatterns": [], 125 | "ignoreExceptions": true, 126 | "statics": "^G._.+$", 127 | "instance": "^M._.+$" 128 | }, 129 | "cloud_types": { 130 | "enabled": true, 131 | "exclude": [], 132 | "reason": "" 133 | }, 134 | "colon_missing_space": { 135 | "enabled": true, 136 | "exclude": [], 137 | "reason": "" 138 | }, 139 | "commented_code": { 140 | "enabled": true, 141 | "exclude": [], 142 | "reason": "" 143 | }, 144 | "constructor_visibility_public": { 145 | "enabled": true, 146 | "exclude": [], 147 | "reason": "" 148 | }, 149 | "contains_tab": { 150 | "enabled": true, 151 | "exclude": [], 152 | "reason": "" 153 | }, 154 | "definitions_top": { 155 | "enabled": true, 156 | "exclude": [], 157 | "reason": "" 158 | }, 159 | "description_empty": { 160 | "enabled": true, 161 | "exclude": [], 162 | "reason": "" 163 | }, 164 | "double_space": { 165 | "enabled": false, 166 | "exclude": [], 167 | "reason": "", 168 | "keywords": true, 169 | "startParen": true, 170 | "endParen": true, 171 | "afterColon": true 172 | }, 173 | "empty_line_in_statement": { 174 | "enabled": true, 175 | "exclude": [], 176 | "reason": "", 177 | "allowChained": false 178 | }, 179 | "empty_statement": { 180 | "enabled": true, 181 | "exclude": [], 182 | "reason": "" 183 | }, 184 | "empty_structure": { 185 | "enabled": true, 186 | "exclude": [], 187 | "reason": "", 188 | "loop": true, 189 | "if": true, 190 | "while": true, 191 | "case": true, 192 | "select": true, 193 | "do": true, 194 | "at": true 195 | }, 196 | "exit_or_check": { 197 | "enabled": true, 198 | "exclude": [], 199 | "reason": "" 200 | }, 201 | "exporting": { 202 | "enabled": true, 203 | "exclude": [], 204 | "reason": "" 205 | }, 206 | "form_no_dash": { 207 | "enabled": true, 208 | "exclude": [], 209 | "reason": "" 210 | }, 211 | "form_tables_obsolete": { 212 | "enabled": true, 213 | "exclude": [], 214 | "reason": "" 215 | }, 216 | "fully_type_constants": { 217 | "enabled": true, 218 | "exclude": [], 219 | "reason": "", 220 | "checkData": true 221 | }, 222 | "functional_writing": { 223 | "enabled": true, 224 | "exclude": [], 225 | "reason": "", 226 | "ignoreExceptions": true 227 | }, 228 | "global_class": { 229 | "enabled": true, 230 | "exclude": [], 231 | "reason": "" 232 | }, 233 | "identical_form_names": { 234 | "enabled": true, 235 | "exclude": [], 236 | "reason": "" 237 | }, 238 | "if_in_if": { 239 | "enabled": true, 240 | "exclude": [], 241 | "reason": "" 242 | }, 243 | "implement_methods": { 244 | "enabled": true, 245 | "exclude": [], 246 | "reason": "" 247 | }, 248 | "in_statement_indentation": { 249 | "enabled": true, 250 | "exclude": [], 251 | "reason": "", 252 | "ignoreExceptions": true 253 | }, 254 | "indentation": { 255 | "enabled": true, 256 | "exclude": [], 257 | "reason": "", 258 | "ignoreExceptions": true, 259 | "alignTryCatch": false, 260 | "globalClassSkipFirst": false, 261 | "ignoreGlobalClassDefinition": false, 262 | "ignoreGlobalInterface": false 263 | }, 264 | "inline_data_old_versions": { 265 | "enabled": true, 266 | "exclude": [], 267 | "reason": "" 268 | }, 269 | "keyword_case": { 270 | "enabled": true, 271 | "exclude": [], 272 | "reason": "", 273 | "style": "upper", 274 | "ignoreExceptions": true, 275 | "ignoreLowerClassImplmentationStatement": true, 276 | "ignoreGlobalClassDefinition": false, 277 | "ignoreGlobalInterface": false, 278 | "ignoreFunctionModuleName": false 279 | }, 280 | "line_length": { 281 | "enabled": true, 282 | "exclude": [], 283 | "reason": "", 284 | "length": 120 285 | }, 286 | "line_only_punc": { 287 | "enabled": true, 288 | "exclude": [], 289 | "reason": "", 290 | "ignoreExceptions": true 291 | }, 292 | "local_class_naming": { 293 | "enabled": true, 294 | "exclude": [], 295 | "reason": "", 296 | "patternKind": "required", 297 | "ignoreNames": [], 298 | "ignorePatterns": [], 299 | "local": "^LCL_.+$", 300 | "exception": "^LCX_.+$", 301 | "test": "^LTCL_.+$" 302 | }, 303 | "local_testclass_location": { 304 | "enabled": true, 305 | "exclude": [], 306 | "reason": "" 307 | }, 308 | "local_variable_names": { 309 | "enabled": true, 310 | "exclude": [], 311 | "reason": "", 312 | "patternKind": "required", 313 | "ignoreNames": [], 314 | "ignorePatterns": [], 315 | "expectedData": "^L._.+$", 316 | "expectedConstant": "^LC_.+$", 317 | "expectedFS": "^$" 318 | }, 319 | "main_file_contents": { 320 | "enabled": true, 321 | "exclude": [], 322 | "reason": "" 323 | }, 324 | "max_one_statement": { 325 | "enabled": true, 326 | "exclude": [], 327 | "reason": "" 328 | }, 329 | "message_exists": { 330 | "enabled": true, 331 | "exclude": [], 332 | "reason": "" 333 | }, 334 | "method_length": { 335 | "enabled": true, 336 | "exclude": [], 337 | "reason": "", 338 | "statements": 100, 339 | "errorWhenEmpty": true, 340 | "ignoreTestClasses": false 341 | }, 342 | "method_parameter_names": { 343 | "enabled": true, 344 | "exclude": [], 345 | "reason": "", 346 | "patternKind": "required", 347 | "ignoreNames": [], 348 | "ignorePatterns": [], 349 | "ignoreExceptions": true, 350 | "importing": "^I._.+$", 351 | "returning": "^R._.+$", 352 | "changing": "^C._.+$", 353 | "exporting": "^E._.+$" 354 | }, 355 | "mix_returning": { 356 | "enabled": true, 357 | "exclude": [], 358 | "reason": "" 359 | }, 360 | "msag_consistency": { 361 | "enabled": true, 362 | "exclude": [], 363 | "reason": "" 364 | }, 365 | "nesting": { 366 | "enabled": true, 367 | "exclude": [], 368 | "reason": "", 369 | "depth": 5 370 | }, 371 | "newline_between_methods": { 372 | "enabled": true, 373 | "exclude": [], 374 | "reason": "", 375 | "count": 3, 376 | "logic": "less" 377 | }, 378 | "no_public_attributes": { 379 | "enabled": false, 380 | "exclude": [], 381 | "reason": "", 382 | "allowReadOnly": false 383 | }, 384 | "object_naming": { 385 | "enabled": true, 386 | "exclude": [], 387 | "reason": "", 388 | "patternKind": "required", 389 | "ignoreNames": [], 390 | "ignorePatterns": [], 391 | "clas": "^ZC(L|X)\\_", 392 | "intf": "^ZIF\\_", 393 | "prog": "^Z", 394 | "fugr": "^Z", 395 | "tabl": "^Z", 396 | "ttyp": "^Z", 397 | "dtel": "^Z", 398 | "doma": "^Z", 399 | "msag": "^Z", 400 | "tran": "^Z", 401 | "enqu": "^EZ", 402 | "auth": "^Z", 403 | "pinf": "^Z", 404 | "idoc": "^Z", 405 | "xslt": "^Z" 406 | }, 407 | "obsolete_statement": { 408 | "enabled": true, 409 | "exclude": [], 410 | "reason": "", 411 | "refresh": true, 412 | "compute": true, 413 | "add": true, 414 | "subtract": true, 415 | "multiply": true, 416 | "move": true, 417 | "divide": true, 418 | "requested": true, 419 | "occurs": true 420 | }, 421 | "parser_error": { 422 | "enabled": true, 423 | "exclude": [], 424 | "reason": "" 425 | }, 426 | "preferred_compare_operator": { 427 | "enabled": true, 428 | "exclude": [], 429 | "reason": "", 430 | "badOperators": [ 431 | "EQ", 432 | "><", 433 | "NE", 434 | "GE", 435 | "GT", 436 | "LT", 437 | "LE" 438 | ] 439 | }, 440 | "release_idoc": { 441 | "enabled": true, 442 | "exclude": [], 443 | "reason": "" 444 | }, 445 | "remove_descriptions": { 446 | "enabled": false, 447 | "exclude": [], 448 | "reason": "", 449 | "ignoreExceptions": false 450 | }, 451 | "rfc_error_handling": { 452 | "enabled": true, 453 | "exclude": [], 454 | "reason": "" 455 | }, 456 | "selection_screen_naming": { 457 | "enabled": true, 458 | "exclude": [], 459 | "reason": "", 460 | "patternKind": "required", 461 | "ignoreNames": [], 462 | "ignorePatterns": [], 463 | "parameter": "^P_.+$", 464 | "selectOption": "^S_.+$" 465 | }, 466 | "sequential_blank": { 467 | "enabled": true, 468 | "exclude": [], 469 | "reason": "", 470 | "lines": 4 471 | }, 472 | "short_case": { 473 | "enabled": true, 474 | "exclude": [], 475 | "reason": "", 476 | "length": 1, 477 | "allow": [] 478 | }, 479 | "sicf_consistency": { 480 | "enabled": true, 481 | "exclude": [], 482 | "reason": "" 483 | }, 484 | "space_before_colon": { 485 | "enabled": true, 486 | "exclude": [], 487 | "reason": "" 488 | }, 489 | "space_before_dot": { 490 | "enabled": true, 491 | "exclude": [], 492 | "reason": "", 493 | "ignoreGlobalDefinition": true, 494 | "ignoreExceptions": true 495 | }, 496 | "start_at_tab": { 497 | "enabled": true, 498 | "exclude": [], 499 | "reason": "" 500 | }, 501 | "superclass_final": { 502 | "enabled": true, 503 | "exclude": [], 504 | "reason": "" 505 | }, 506 | "tabl_enhancement_category": { 507 | "enabled": true, 508 | "exclude": [], 509 | "reason": "" 510 | }, 511 | "type_begin_single_include": { 512 | "enabled": true, 513 | "exclude": [], 514 | "reason": "" 515 | }, 516 | "type_form_parameters": { 517 | "enabled": true, 518 | "exclude": [], 519 | "reason": "" 520 | }, 521 | "types_naming": { 522 | "enabled": true, 523 | "exclude": [], 524 | "reason": "", 525 | "pattern": "^TY_.+$" 526 | }, 527 | "unreachable_code": { 528 | "enabled": true, 529 | "exclude": [], 530 | "reason": "" 531 | }, 532 | "use_new": { 533 | "enabled": true, 534 | "exclude": [], 535 | "reason": "" 536 | }, 537 | "when_others_last": { 538 | "enabled": true, 539 | "exclude": [], 540 | "reason": "" 541 | }, 542 | "whitespace_end": { 543 | "enabled": true, 544 | "exclude": [], 545 | "reason": "" 546 | }, 547 | "xml_consistency": { 548 | "enabled": true, 549 | "exclude": [], 550 | "reason": "" 551 | } 552 | } 553 | } 554 | -------------------------------------------------------------------------------- /src/mqtt/package.devc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | MQTT Client 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/mqtt/packets/package.devc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Packets 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_connack.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_connack DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | TYPES: 10 | ty_return_code TYPE x LENGTH 1 . 11 | 12 | CONSTANTS: 13 | BEGIN OF gc_return_code, 14 | accepted TYPE ty_return_code VALUE '00', 15 | unacceptabe_protocol TYPE ty_return_code VALUE '01', 16 | identifer_rejected TYPE ty_return_code VALUE '02', 17 | server_unavailable TYPE ty_return_code VALUE '03', 18 | bad_username_or_password TYPE ty_return_code VALUE '04', 19 | not_authorized TYPE ty_return_code VALUE '05', 20 | END OF gc_return_code . 21 | 22 | METHODS get_session_present 23 | RETURNING 24 | VALUE(rv_session_present) TYPE abap_bool . 25 | METHODS get_return_code 26 | RETURNING 27 | VALUE(rv_return_code) TYPE ty_return_code . 28 | PROTECTED SECTION. 29 | 30 | DATA mv_session_present TYPE abap_bool . 31 | DATA mv_return_code TYPE ty_return_code . 32 | PRIVATE SECTION. 33 | ENDCLASS. 34 | 35 | 36 | 37 | CLASS ZCL_MQTT_PACKET_CONNACK IMPLEMENTATION. 38 | 39 | 40 | METHOD get_return_code. 41 | 42 | rv_return_code = mv_return_code. 43 | 44 | ENDMETHOD. 45 | 46 | 47 | METHOD get_session_present. 48 | 49 | rv_session_present = mv_session_present. 50 | 51 | ENDMETHOD. 52 | 53 | 54 | METHOD zif_mqtt_packet~decode. 55 | 56 | CONSTANTS: lc_header TYPE xstring VALUE '2002'. 57 | 58 | ASSERT io_stream->eat_hex( 2 ) = lc_header. 59 | 60 | CASE io_stream->eat_hex( 1 ). 61 | WHEN '00'. 62 | mv_session_present = abap_false. 63 | WHEN '01'. 64 | mv_session_present = abap_true. 65 | WHEN OTHERS. 66 | ASSERT 0 = 1. 67 | ENDCASE. 68 | 69 | mv_return_code = io_stream->eat_hex( 1 ). 70 | 71 | ASSERT io_stream->get_length( ) = 0. 72 | 73 | ENDMETHOD. 74 | 75 | 76 | METHOD zif_mqtt_packet~encode. 77 | 78 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 79 | 80 | IF mv_session_present = abap_true. 81 | lo_payload->add_hex( '01' ). 82 | ELSE. 83 | lo_payload->add_hex( '00' ). 84 | ENDIF. 85 | 86 | lo_payload->add_hex( mv_return_code ). 87 | 88 | ro_stream = NEW #( ). 89 | 90 | ro_stream->add_packet( 91 | ii_packet = me 92 | io_payload = lo_payload ). 93 | 94 | ENDMETHOD. 95 | 96 | 97 | METHOD zif_mqtt_packet~get_type. 98 | 99 | rv_value = zif_mqtt_constants=>gc_packets-connack. 100 | 101 | ENDMETHOD. 102 | ENDCLASS. 103 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_connack.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_connack. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE '20020000'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->get_return_code( ) 35 | exp = '00' ). 36 | 37 | cl_abap_unit_assert=>assert_equals( 38 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 39 | exp = lc_hex ). 40 | 41 | ENDMETHOD. 42 | 43 | ENDCLASS. 44 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_connack.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_CONNACK 7 | E 8 | CONNACK 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_connect.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_connect DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS constructor 10 | IMPORTING 11 | !iv_clean_session TYPE abap_bool DEFAULT abap_true 12 | !iv_username TYPE string OPTIONAL 13 | !iv_password TYPE string OPTIONAL 14 | !iv_client_id TYPE string OPTIONAL 15 | iv_will_qos TYPE zif_mqtt_packet=>ty_qos OPTIONAL 16 | is_will_message TYPE zif_mqtt_packet=>ty_message OPTIONAL 17 | iv_will_retain TYPE abap_bool OPTIONAL 18 | !iv_keep_alive TYPE i DEFAULT 30 . 19 | PROTECTED SECTION. 20 | 21 | TYPES: 22 | BEGIN OF ty_flags, 23 | username TYPE abap_bool, 24 | password TYPE abap_bool, 25 | will_retain TYPE abap_bool, 26 | will_qos TYPE zif_mqtt_packet=>ty_qos, 27 | will_flag TYPE abap_bool, 28 | clean_session TYPE abap_bool, 29 | END OF ty_flags . 30 | 31 | CONSTANTS lc_protocol_name TYPE string VALUE 'MQTT' ##NO_TEXT. 32 | CONSTANTS lc_protocol_level TYPE xstring VALUE '04' ##NO_TEXT. 33 | DATA mv_username TYPE string . 34 | DATA mv_password TYPE xstring . 35 | DATA mv_client_id TYPE string . 36 | DATA mv_will_qos TYPE zif_mqtt_packet=>ty_qos . 37 | DATA ms_will_message TYPE zif_mqtt_packet=>ty_message . 38 | DATA mv_will_retain TYPE abap_bool . 39 | DATA: 40 | mv_keep_alive TYPE x LENGTH 2 . 41 | DATA mv_clean_session TYPE abap_bool . 42 | 43 | CLASS-METHODS decode_flags 44 | IMPORTING 45 | !iv_hex TYPE xsequence 46 | RETURNING 47 | VALUE(rs_flags) TYPE ty_flags . 48 | CLASS-METHODS encode_flags 49 | IMPORTING 50 | !is_flags TYPE ty_flags 51 | RETURNING 52 | VALUE(rv_hex) TYPE xstring . 53 | PRIVATE SECTION. 54 | ENDCLASS. 55 | 56 | 57 | 58 | CLASS ZCL_MQTT_PACKET_CONNECT IMPLEMENTATION. 59 | 60 | 61 | METHOD constructor. 62 | 63 | mv_clean_session = iv_clean_session. 64 | mv_client_id = iv_client_id. 65 | mv_keep_alive = iv_keep_alive. 66 | mv_password = cl_binary_convert=>string_to_xstring_utf8( CONV #( iv_password ) ). 67 | mv_username = iv_username. 68 | ms_will_message = is_will_message. 69 | mv_will_qos = iv_will_qos. 70 | mv_will_retain = iv_will_retain. 71 | 72 | ENDMETHOD. 73 | 74 | 75 | METHOD decode_flags. 76 | 77 | DATA: lv_int TYPE i. 78 | 79 | lv_int = iv_hex. 80 | 81 | IF lv_int DIV 128 = 1. 82 | rs_flags-username = abap_true. 83 | ENDIF. 84 | 85 | IF lv_int DIV 64 = 1. 86 | rs_flags-password = abap_true. 87 | ENDIF. 88 | 89 | IF lv_int DIV 32 = 1. 90 | rs_flags-will_retain = abap_true. 91 | ENDIF. 92 | 93 | rs_flags-will_qos = ( lv_int DIV 8 ) MOD 4. 94 | 95 | IF lv_int DIV 4 = 1. 96 | rs_flags-will_flag = abap_true. 97 | ENDIF. 98 | 99 | IF lv_int DIV 2 = 1. 100 | rs_flags-clean_session = abap_true. 101 | ENDIF. 102 | 103 | ENDMETHOD. 104 | 105 | 106 | METHOD encode_flags. 107 | 108 | DATA: lv_int TYPE i, 109 | lv_hex TYPE x LENGTH 1. 110 | 111 | 112 | IF is_flags-username = abap_true. 113 | lv_int = lv_int + 128. 114 | ENDIF. 115 | 116 | IF is_flags-password = abap_true. 117 | lv_int = lv_int + 64. 118 | ENDIF. 119 | 120 | IF is_flags-will_retain = abap_true. 121 | lv_int = lv_int + 32. 122 | ENDIF. 123 | 124 | lv_int = lv_int + is_flags-will_qos * 8. 125 | 126 | IF is_flags-will_flag = abap_true. 127 | lv_int = lv_int + 4. 128 | ENDIF. 129 | 130 | IF is_flags-clean_session = abap_true. 131 | lv_int = lv_int + 2. 132 | ENDIF. 133 | 134 | lv_hex = lv_int. 135 | rv_hex = lv_hex. 136 | 137 | ENDMETHOD. 138 | 139 | 140 | METHOD zif_mqtt_packet~decode. 141 | 142 | DATA: lv_length TYPE i. 143 | 144 | ASSERT io_stream->eat_hex( 1 ) = '10'. 145 | io_stream->eat_length( ). 146 | ASSERT io_stream->eat_utf8( ) = lc_protocol_name. 147 | ASSERT io_stream->eat_hex( 1 ) = lc_protocol_level. 148 | 149 | DATA(ls_flags) = decode_flags( io_stream->eat_hex( 1 ) ). 150 | mv_clean_session = ls_flags-clean_session. 151 | mv_will_qos = ls_flags-will_qos. 152 | mv_will_retain = ls_flags-will_retain. 153 | 154 | mv_keep_alive = io_stream->eat_hex( 2 ). 155 | 156 | mv_client_id = io_stream->eat_utf8( ). 157 | 158 | IF ls_flags-will_flag = abap_true. 159 | ms_will_message-topic = io_stream->eat_utf8( ). 160 | lv_length = io_stream->eat_hex( 2 ). 161 | ms_will_message-message = io_stream->eat_hex( lv_length ). 162 | ENDIF. 163 | 164 | IF ls_flags-username = abap_true. 165 | mv_username = io_stream->eat_utf8( ). 166 | ENDIF. 167 | 168 | IF ls_flags-password = abap_true. 169 | lv_length = io_stream->eat_hex( 2 ). 170 | mv_password = io_stream->eat_hex( lv_length ). 171 | ENDIF. 172 | 173 | ASSERT io_stream->get_length( ) = 0. 174 | 175 | ENDMETHOD. 176 | 177 | 178 | METHOD zif_mqtt_packet~encode. 179 | 180 | DATA: lv_length TYPE x LENGTH 2. 181 | 182 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 183 | 184 | lo_payload->add_utf8( lc_protocol_name ). 185 | 186 | lo_payload->add_hex( lc_protocol_level ). 187 | 188 | lo_payload->add_hex( encode_flags( VALUE #( 189 | username = boolc( NOT mv_username IS INITIAL ) 190 | password = boolc( NOT mv_password IS INITIAL ) 191 | will_retain = mv_will_retain 192 | will_qos = mv_will_qos 193 | will_flag = boolc( NOT ms_will_message IS INITIAL ) 194 | clean_session = mv_clean_session ) ) ). 195 | 196 | lo_payload->add_hex( mv_keep_alive ). 197 | 198 | lo_payload->add_utf8( mv_client_id ). 199 | 200 | IF NOT ms_will_message IS INITIAL. 201 | lo_payload->add_utf8( ms_will_message-topic ). 202 | lv_length = xstrlen( ms_will_message-message ). 203 | lo_payload->add_hex( lv_length ). 204 | lo_payload->add_hex( ms_will_message-message ). 205 | ENDIF. 206 | 207 | IF NOT mv_username IS INITIAL. 208 | lo_payload->add_utf8( mv_username ). 209 | ENDIF. 210 | 211 | IF NOT mv_password IS INITIAL. 212 | lv_length = xstrlen( mv_password ). " <-- fix, was xstrlen( ms_will_message-message ). 213 | lo_payload->add_hex( lv_length ). 214 | lo_payload->add_hex( mv_password ). 215 | ENDIF. 216 | 217 | ro_stream = NEW #( ). 218 | 219 | ro_stream->add_packet( 220 | ii_packet = me 221 | io_payload = lo_payload ). 222 | 223 | ENDMETHOD. 224 | 225 | 226 | METHOD zif_mqtt_packet~get_type. 227 | 228 | rv_value = zif_mqtt_constants=>gc_packets-connect. 229 | 230 | ENDMETHOD. 231 | ENDCLASS. 232 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_connect.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | METHODS: 8 | test FOR TESTING, 9 | test_new FOR TESTING. 10 | 11 | ENDCLASS. 12 | 13 | 14 | CLASS ltcl_test IMPLEMENTATION. 15 | 16 | METHOD test. 17 | 18 | CONSTANTS: lc_hex TYPE xstring VALUE '100C00044D5154540402001E0000'. 19 | 20 | DATA(lo_encoded) = NEW zcl_mqtt_packet_connect( ). 21 | 22 | DATA(lv_hex) = lo_encoded->zif_mqtt_packet~encode( )->get_hex( ). 23 | 24 | cl_abap_unit_assert=>assert_equals( 25 | act = lv_hex 26 | exp = lc_hex ). 27 | 28 | ENDMETHOD. 29 | 30 | METHOD test_new. 31 | 32 | CONSTANTS: lc_hex TYPE xstring VALUE '100C00044D5154540402001E0000'. 33 | 34 | DATA(lo_connect) = NEW zcl_mqtt_packet_connect( ). 35 | lo_connect->zif_mqtt_packet~decode( NEW zcl_mqtt_stream( lc_hex ) ). 36 | 37 | DATA(lv_hex) = lo_connect->zif_mqtt_packet~encode( )->get_hex( ). 38 | 39 | cl_abap_unit_assert=>assert_equals( 40 | act = lv_hex 41 | exp = lc_hex ). 42 | 43 | ENDMETHOD. 44 | 45 | ENDCLASS. 46 | 47 | 48 | CLASS ltcl_flags DEFINITION DEFERRED. 49 | CLASS zcl_mqtt_packet_connect DEFINITION LOCAL FRIENDS ltcl_flags. 50 | 51 | CLASS ltcl_flags DEFINITION FOR TESTING 52 | DURATION SHORT 53 | RISK LEVEL HARMLESS FINAL. 54 | 55 | PRIVATE SECTION. 56 | DATA: mo_cut TYPE REF TO zcl_mqtt_packet_connect. 57 | 58 | METHODS: setup, 59 | test FOR TESTING. 60 | 61 | ENDCLASS. 62 | 63 | 64 | CLASS ltcl_flags IMPLEMENTATION. 65 | 66 | METHOD setup. 67 | mo_cut = NEW #( ). 68 | ENDMETHOD. 69 | 70 | METHOD test. 71 | 72 | CONSTANTS: lc_hex TYPE x LENGTH 1 VALUE '02'. 73 | 74 | DATA: ls_flags TYPE zcl_mqtt_packet_connect=>ty_flags. 75 | 76 | 77 | ls_flags = mo_cut->decode_flags( lc_hex ). 78 | 79 | DATA(ls_expected) = VALUE zcl_mqtt_packet_connect=>ty_flags( 80 | username = abap_false 81 | password = abap_false 82 | will_retain = abap_false 83 | will_qos = zif_mqtt_packet=>gc_qos-at_most_once 84 | will_flag = abap_false 85 | clean_session = abap_true ). 86 | 87 | cl_abap_unit_assert=>assert_equals( 88 | act = ls_flags 89 | exp = ls_expected ). 90 | 91 | cl_abap_unit_assert=>assert_equals( 92 | act = mo_cut->encode_flags( ls_flags ) 93 | exp = CONV xstring( lc_hex ) ). 94 | 95 | ENDMETHOD. 96 | 97 | ENDCLASS. 98 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_connect.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_CONNECT 7 | E 8 | CONNECT 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_disconnect.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_disconnect DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | PROTECTED SECTION. 9 | PRIVATE SECTION. 10 | ENDCLASS. 11 | 12 | 13 | 14 | CLASS ZCL_MQTT_PACKET_DISCONNECT IMPLEMENTATION. 15 | 16 | 17 | METHOD zif_mqtt_packet~decode. 18 | 19 | ASSERT io_stream->eat_hex( 2 ) = 'E000'. 20 | 21 | ENDMETHOD. 22 | 23 | 24 | METHOD zif_mqtt_packet~encode. 25 | 26 | ro_stream = NEW #( ). 27 | 28 | ro_stream->add_packet( me ). 29 | 30 | ENDMETHOD. 31 | 32 | 33 | METHOD zif_mqtt_packet~get_type. 34 | 35 | rv_value = zif_mqtt_constants=>gc_packets-disconnect. 36 | 37 | ENDMETHOD. 38 | ENDCLASS. 39 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_disconnect.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | METHODS: test FOR TESTING. 8 | 9 | ENDCLASS. 10 | 11 | 12 | CLASS ltcl_test IMPLEMENTATION. 13 | 14 | METHOD test. 15 | 16 | DATA(lo_connect) = NEW zcl_mqtt_packet_disconnect( ). 17 | 18 | DATA(lv_hex) = lo_connect->zif_mqtt_packet~encode( )->get_hex( ). 19 | 20 | cl_abap_unit_assert=>assert_equals( 21 | act = lv_hex 22 | exp = 'E000' ). 23 | 24 | ENDMETHOD. 25 | 26 | ENDCLASS. 27 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_disconnect.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_DISCONNECT 7 | E 8 | DISCONNECT 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pingreq.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_pingreq DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | ALIASES decode 10 | FOR zif_mqtt_packet~decode . 11 | ALIASES encode 12 | FOR zif_mqtt_packet~encode . 13 | ALIASES get_type 14 | FOR zif_mqtt_packet~get_type . 15 | PROTECTED SECTION. 16 | PRIVATE SECTION. 17 | ENDCLASS. 18 | 19 | 20 | 21 | CLASS ZCL_MQTT_PACKET_PINGREQ IMPLEMENTATION. 22 | 23 | 24 | METHOD zif_mqtt_packet~decode. 25 | 26 | ASSERT io_stream->eat_hex( 2 ) = 'C000'. 27 | 28 | ENDMETHOD. 29 | 30 | 31 | METHOD zif_mqtt_packet~encode. 32 | 33 | ro_stream = NEW #( ). 34 | 35 | ro_stream->add_packet( me ). 36 | 37 | ENDMETHOD. 38 | 39 | 40 | METHOD zif_mqtt_packet~get_type. 41 | 42 | rv_value = zif_mqtt_constants=>gc_packets-pingreq. 43 | 44 | ENDMETHOD. 45 | ENDCLASS. 46 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pingreq.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mi_cut TYPE REF TO zif_mqtt_packet. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | ENDCLASS. 14 | 15 | 16 | CLASS ltcl_test IMPLEMENTATION. 17 | 18 | METHOD setup. 19 | mi_cut = NEW zcl_mqtt_packet_pingreq( ). 20 | ENDMETHOD. 21 | 22 | METHOD test. 23 | 24 | DATA(lv_hex) = mi_cut->encode( )->get_hex( ). 25 | 26 | cl_abap_unit_assert=>assert_equals( 27 | act = lv_hex 28 | exp = 'C000' ). 29 | 30 | ENDMETHOD. 31 | 32 | ENDCLASS. 33 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pingreq.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PINGREQ 7 | E 8 | PINGREQ 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pingresp.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_pingresp DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | PROTECTED SECTION. 9 | PRIVATE SECTION. 10 | ENDCLASS. 11 | 12 | 13 | 14 | CLASS ZCL_MQTT_PACKET_PINGRESP IMPLEMENTATION. 15 | 16 | 17 | METHOD zif_mqtt_packet~decode. 18 | 19 | ASSERT io_stream->eat_hex( 2 ) = 'D000'. 20 | 21 | ENDMETHOD. 22 | 23 | 24 | METHOD zif_mqtt_packet~encode. 25 | 26 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 27 | 28 | ro_stream = NEW #( ). 29 | 30 | ro_stream->add_packet( 31 | ii_packet = me 32 | io_payload = lo_payload ). 33 | 34 | ENDMETHOD. 35 | 36 | 37 | METHOD zif_mqtt_packet~get_type. 38 | 39 | rv_value = zif_mqtt_constants=>gc_packets-pingresp. 40 | 41 | ENDMETHOD. 42 | ENDCLASS. 43 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pingresp.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_pingresp. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE 'D000'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pingresp.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PINGRESP 7 | E 8 | PINGRESP 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_puback.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_puback DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS constructor 10 | IMPORTING 11 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 12 | METHODS get_packet_identifier 13 | RETURNING 14 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 15 | METHODS set_packet_identifier 16 | IMPORTING 17 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 18 | PROTECTED SECTION. 19 | 20 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 21 | PRIVATE SECTION. 22 | ENDCLASS. 23 | 24 | 25 | 26 | CLASS ZCL_MQTT_PACKET_PUBACK IMPLEMENTATION. 27 | 28 | 29 | METHOD constructor. 30 | 31 | mv_packet_identifier = iv_packet_identifier. 32 | 33 | ENDMETHOD. 34 | 35 | 36 | METHOD get_packet_identifier. 37 | 38 | rv_packet_identifier = mv_packet_identifier. 39 | 40 | ENDMETHOD. 41 | 42 | 43 | METHOD set_packet_identifier. 44 | 45 | mv_packet_identifier = iv_packet_identifier. 46 | 47 | ENDMETHOD. 48 | 49 | 50 | METHOD zif_mqtt_packet~decode. 51 | 52 | ASSERT io_stream->eat_hex( 1 ) = '42'. 53 | 54 | io_stream->eat_length( ). 55 | 56 | mv_packet_identifier = io_stream->eat_hex( 2 ). 57 | 58 | ENDMETHOD. 59 | 60 | 61 | METHOD zif_mqtt_packet~encode. 62 | 63 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 64 | 65 | ASSERT NOT mv_packet_identifier IS INITIAL. 66 | lo_payload->add_hex( mv_packet_identifier ). 67 | 68 | ro_stream = NEW #( ). 69 | 70 | ro_stream->add_packet( 71 | ii_packet = me 72 | iv_flags = 2 73 | io_payload = lo_payload ). 74 | 75 | ENDMETHOD. 76 | 77 | 78 | METHOD zif_mqtt_packet~get_type. 79 | 80 | rv_value = zif_mqtt_constants=>gc_packets-puback. 81 | 82 | ENDMETHOD. 83 | ENDCLASS. 84 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_puback.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_puback. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE '42020001'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_puback.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PUBACK 7 | E 8 | PUBACK 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubcomp.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_pubcomp DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS constructor 10 | IMPORTING 11 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 12 | METHODS get_packet_identifier 13 | RETURNING 14 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 15 | METHODS set_packet_identifier 16 | IMPORTING 17 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 18 | PROTECTED SECTION. 19 | 20 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 21 | PRIVATE SECTION. 22 | ENDCLASS. 23 | 24 | 25 | 26 | CLASS ZCL_MQTT_PACKET_PUBCOMP IMPLEMENTATION. 27 | 28 | 29 | METHOD constructor. 30 | 31 | mv_packet_identifier = iv_packet_identifier. 32 | 33 | ENDMETHOD. 34 | 35 | 36 | METHOD get_packet_identifier. 37 | 38 | rv_packet_identifier = mv_packet_identifier. 39 | 40 | ENDMETHOD. 41 | 42 | 43 | METHOD set_packet_identifier. 44 | 45 | mv_packet_identifier = iv_packet_identifier. 46 | 47 | ENDMETHOD. 48 | 49 | 50 | METHOD zif_mqtt_packet~decode. 51 | 52 | ASSERT io_stream->eat_hex( 1 ) = '72'. 53 | 54 | io_stream->eat_length( ). 55 | 56 | mv_packet_identifier = io_stream->eat_hex( 2 ). 57 | 58 | ENDMETHOD. 59 | 60 | 61 | METHOD zif_mqtt_packet~encode. 62 | 63 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 64 | 65 | ASSERT NOT mv_packet_identifier IS INITIAL. 66 | lo_payload->add_hex( mv_packet_identifier ). 67 | 68 | ro_stream = NEW #( ). 69 | 70 | ro_stream->add_packet( 71 | ii_packet = me 72 | iv_flags = 2 73 | io_payload = lo_payload ). 74 | 75 | ENDMETHOD. 76 | 77 | 78 | METHOD zif_mqtt_packet~get_type. 79 | 80 | rv_value = zif_mqtt_constants=>gc_packets-pubcomp. 81 | 82 | ENDMETHOD. 83 | ENDCLASS. 84 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubcomp.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_pubcomp. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE '72020001'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubcomp.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PUBCOMP 7 | E 8 | PUBCOMP 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_publish.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_publish DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | ALIASES decode 10 | FOR zif_mqtt_packet~decode . 11 | ALIASES encode 12 | FOR zif_mqtt_packet~encode . 13 | ALIASES get_type 14 | FOR zif_mqtt_packet~get_type . 15 | 16 | METHODS get_message 17 | RETURNING 18 | VALUE(rs_message) TYPE zif_mqtt_packet=>ty_message . 19 | METHODS set_message 20 | IMPORTING 21 | !is_message TYPE zif_mqtt_packet=>ty_message . 22 | METHODS constructor 23 | IMPORTING 24 | !is_message TYPE zif_mqtt_packet=>ty_message OPTIONAL 25 | !iv_dup_flag TYPE abap_bool OPTIONAL 26 | !iv_qos_level TYPE zif_mqtt_packet=>ty_qos OPTIONAL 27 | !iv_retain TYPE abap_bool OPTIONAL 28 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 29 | METHODS get_packet_identifier 30 | RETURNING 31 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 32 | METHODS set_packet_identifier 33 | IMPORTING 34 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 35 | PROTECTED SECTION. 36 | 37 | DATA ms_message TYPE zif_mqtt_packet=>ty_message . 38 | DATA mv_dup_flag TYPE abap_bool . 39 | DATA mv_qos_level TYPE zif_mqtt_packet=>ty_qos . 40 | DATA mv_retain TYPE abap_bool . 41 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 42 | 43 | CLASS-METHODS decode_flags 44 | IMPORTING 45 | !iv_flags TYPE i 46 | EXPORTING 47 | !ev_qos_level TYPE zif_mqtt_packet=>ty_qos 48 | !ev_retain TYPE abap_bool 49 | !ev_dup_flag TYPE abap_bool . 50 | CLASS-METHODS encode_flags 51 | IMPORTING 52 | !iv_dup_flag TYPE abap_bool 53 | !iv_qos_level TYPE zif_mqtt_packet=>ty_qos 54 | !iv_retain TYPE abap_bool 55 | RETURNING 56 | VALUE(rv_flags) TYPE i . 57 | PRIVATE SECTION. 58 | ENDCLASS. 59 | 60 | 61 | 62 | CLASS ZCL_MQTT_PACKET_PUBLISH IMPLEMENTATION. 63 | 64 | 65 | METHOD constructor. 66 | 67 | ms_message = is_message. 68 | mv_dup_flag = iv_dup_flag. 69 | mv_qos_level = iv_qos_level. 70 | mv_retain = iv_retain. 71 | mv_packet_identifier = iv_packet_identifier. 72 | 73 | ENDMETHOD. 74 | 75 | 76 | METHOD decode_flags. 77 | 78 | IF iv_flags MOD 2 = 1. 79 | ev_retain = abap_true. 80 | ELSE. 81 | ev_retain = abap_false. 82 | ENDIF. 83 | 84 | ev_qos_level = ( iv_flags DIV 2 ) MOD 4. 85 | 86 | IF iv_flags MOD 8 = 1. 87 | ev_dup_flag = abap_true. 88 | ELSE. 89 | ev_dup_flag = abap_false. 90 | ENDIF. 91 | 92 | ENDMETHOD. 93 | 94 | 95 | METHOD encode_flags. 96 | 97 | IF iv_retain = abap_true. 98 | rv_flags = 1. 99 | ENDIF. 100 | 101 | rv_flags = rv_flags + iv_qos_level * 2. 102 | 103 | IF iv_dup_flag = abap_true. 104 | rv_flags = rv_flags + 8. 105 | ENDIF. 106 | 107 | ENDMETHOD. 108 | 109 | 110 | METHOD get_message. 111 | 112 | rs_message = ms_message. 113 | 114 | ENDMETHOD. 115 | 116 | 117 | METHOD get_packet_identifier. 118 | 119 | rv_packet_identifier = mv_packet_identifier. 120 | 121 | ENDMETHOD. 122 | 123 | 124 | METHOD set_message. 125 | 126 | ms_message = is_message. 127 | 128 | ENDMETHOD. 129 | 130 | 131 | METHOD set_packet_identifier. 132 | 133 | mv_packet_identifier = iv_packet_identifier. 134 | 135 | ENDMETHOD. 136 | 137 | 138 | METHOD zif_mqtt_packet~decode. 139 | 140 | DATA(lv_hex) = io_stream->eat_hex( 1 ). 141 | 142 | zcl_mqtt_packet_publish=>decode_flags( 143 | EXPORTING 144 | iv_flags = CONV #( lv_hex ) 145 | IMPORTING 146 | ev_qos_level = mv_qos_level 147 | ev_retain = mv_retain 148 | ev_dup_flag = mv_dup_flag ). 149 | 150 | io_stream->eat_length( ). 151 | 152 | ms_message-topic = io_stream->eat_utf8( ). 153 | 154 | IF mv_qos_level > 0. 155 | mv_packet_identifier = io_stream->eat_hex( 2 ). 156 | ENDIF. 157 | 158 | ms_message-message = io_stream->eat_hex( io_stream->get_length( ) ). 159 | 160 | ASSERT io_stream->get_length( ) = 0. 161 | 162 | ENDMETHOD. 163 | 164 | 165 | METHOD zif_mqtt_packet~encode. 166 | 167 | ASSERT NOT ms_message-topic IS INITIAL. 168 | ASSERT NOT ms_message-message IS INITIAL. 169 | 170 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 171 | 172 | IF mv_qos_level > 0. 173 | ASSERT NOT mv_packet_identifier IS INITIAL. 174 | lo_payload->add_hex( mv_packet_identifier ). 175 | ENDIF. 176 | 177 | lo_payload->add_utf8( ms_message-topic ). 178 | lo_payload->add_hex( ms_message-message ). 179 | 180 | DATA(lv_flags) = encode_flags( 181 | iv_dup_flag = mv_dup_flag 182 | iv_qos_level = mv_qos_level 183 | iv_retain = mv_retain ). 184 | 185 | ro_stream = NEW #( ). 186 | 187 | ro_stream->add_packet( 188 | ii_packet = me 189 | io_payload = lo_payload ). 190 | 191 | ENDMETHOD. 192 | 193 | 194 | METHOD zif_mqtt_packet~get_type. 195 | 196 | rv_value = zif_mqtt_constants=>gc_packets-publish. 197 | 198 | ENDMETHOD. 199 | ENDCLASS. 200 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_publish.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_publish. 9 | 10 | METHODS: 11 | setup, 12 | decode FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD decode. 26 | 27 | CONSTANTS: lc_topic TYPE string VALUE 'topic', 28 | lc_message TYPE xstring VALUE '001122334455'. 29 | 30 | 31 | mo_cut->set_message( VALUE #( 32 | topic = lc_topic 33 | message = lc_message ) ). 34 | 35 | mo_cut->zif_mqtt_packet~decode( mo_cut->zif_mqtt_packet~encode( ) ). 36 | 37 | cl_abap_unit_assert=>assert_equals( 38 | act = mo_cut->get_message( )-topic 39 | exp = lc_topic ). 40 | 41 | cl_abap_unit_assert=>assert_equals( 42 | act = mo_cut->get_message( )-message 43 | exp = lc_message ). 44 | 45 | ENDMETHOD. 46 | 47 | ENDCLASS. 48 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_publish.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PUBLISH 7 | E 8 | PUBLISH 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubrec.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_pubrec DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS constuctor 10 | IMPORTING 11 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 12 | METHODS get_packet_identifier 13 | RETURNING 14 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 15 | METHODS set_packet_identifier 16 | IMPORTING 17 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 18 | PROTECTED SECTION. 19 | 20 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 21 | PRIVATE SECTION. 22 | ENDCLASS. 23 | 24 | 25 | 26 | CLASS ZCL_MQTT_PACKET_PUBREC IMPLEMENTATION. 27 | 28 | 29 | METHOD constuctor. 30 | 31 | mv_packet_identifier = iv_packet_identifier. 32 | 33 | ENDMETHOD. 34 | 35 | 36 | METHOD get_packet_identifier. 37 | 38 | rv_packet_identifier = mv_packet_identifier. 39 | 40 | ENDMETHOD. 41 | 42 | 43 | METHOD set_packet_identifier. 44 | 45 | mv_packet_identifier = iv_packet_identifier. 46 | 47 | ENDMETHOD. 48 | 49 | 50 | METHOD zif_mqtt_packet~decode. 51 | 52 | ASSERT io_stream->eat_hex( 1 ) = '52'. 53 | 54 | io_stream->eat_length( ). 55 | 56 | mv_packet_identifier = io_stream->eat_hex( 2 ). 57 | 58 | ENDMETHOD. 59 | 60 | 61 | METHOD zif_mqtt_packet~encode. 62 | 63 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 64 | 65 | ASSERT NOT mv_packet_identifier IS INITIAL. 66 | lo_payload->add_hex( mv_packet_identifier ). 67 | 68 | ro_stream = NEW #( ). 69 | 70 | ro_stream->add_packet( 71 | ii_packet = me 72 | iv_flags = 2 73 | io_payload = lo_payload ). 74 | 75 | ENDMETHOD. 76 | 77 | 78 | METHOD zif_mqtt_packet~get_type. 79 | 80 | rv_value = zif_mqtt_constants=>gc_packets-pubrec. 81 | 82 | ENDMETHOD. 83 | ENDCLASS. 84 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubrec.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_pubrec. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE '52020001'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubrec.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PUBREC 7 | E 8 | PUBREC 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubrel.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_pubrel DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS constructor 10 | IMPORTING 11 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 12 | METHODS get_packet_identifier 13 | RETURNING 14 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 15 | METHODS set_packet_identifier 16 | IMPORTING 17 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 18 | PROTECTED SECTION. 19 | 20 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 21 | PRIVATE SECTION. 22 | ENDCLASS. 23 | 24 | 25 | 26 | CLASS ZCL_MQTT_PACKET_PUBREL IMPLEMENTATION. 27 | 28 | 29 | METHOD constructor. 30 | 31 | mv_packet_identifier = iv_packet_identifier. 32 | 33 | ENDMETHOD. 34 | 35 | 36 | METHOD get_packet_identifier. 37 | 38 | rv_packet_identifier = mv_packet_identifier. 39 | 40 | ENDMETHOD. 41 | 42 | 43 | METHOD set_packet_identifier. 44 | 45 | mv_packet_identifier = iv_packet_identifier. 46 | 47 | ENDMETHOD. 48 | 49 | 50 | METHOD zif_mqtt_packet~decode. 51 | 52 | ASSERT io_stream->eat_hex( 1 ) = '62'. 53 | 54 | io_stream->eat_length( ). 55 | 56 | mv_packet_identifier = io_stream->eat_hex( 2 ). 57 | 58 | ENDMETHOD. 59 | 60 | 61 | METHOD zif_mqtt_packet~encode. 62 | 63 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 64 | 65 | ASSERT NOT mv_packet_identifier IS INITIAL. 66 | lo_payload->add_hex( mv_packet_identifier ). 67 | 68 | ro_stream = NEW #( ). 69 | 70 | ro_stream->add_packet( 71 | ii_packet = me 72 | iv_flags = 2 73 | io_payload = lo_payload ). 74 | 75 | ENDMETHOD. 76 | 77 | 78 | METHOD zif_mqtt_packet~get_type. 79 | 80 | rv_value = zif_mqtt_constants=>gc_packets-pubrel. 81 | 82 | ENDMETHOD. 83 | ENDCLASS. 84 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubrel.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_pubrel. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE '62020001'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_pubrel.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_PUBREL 7 | E 8 | PUBREL 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_suback.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_suback DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | TYPES: 10 | ty_hex TYPE x LENGTH 1 . 11 | TYPES: 12 | ty_return_codes TYPE STANDARD TABLE OF ty_hex WITH EMPTY KEY . 13 | 14 | METHODS set_return_codes 15 | IMPORTING 16 | !it_return_codes TYPE ty_return_codes . 17 | METHODS get_return_codes 18 | RETURNING 19 | VALUE(rt_return_codes) TYPE ty_return_codes . 20 | METHODS constructor 21 | IMPORTING 22 | !it_return_codes TYPE ty_return_codes OPTIONAL 23 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 24 | METHODS get_packet_identifier 25 | RETURNING 26 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 27 | METHODS set_packet_identifier 28 | IMPORTING 29 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 30 | PROTECTED SECTION. 31 | 32 | DATA mt_return_codes TYPE ty_return_codes . 33 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 34 | PRIVATE SECTION. 35 | ENDCLASS. 36 | 37 | 38 | 39 | CLASS ZCL_MQTT_PACKET_SUBACK IMPLEMENTATION. 40 | 41 | 42 | METHOD constructor. 43 | 44 | mv_packet_identifier = iv_packet_identifier. 45 | mt_return_codes = it_return_codes. 46 | 47 | ENDMETHOD. 48 | 49 | 50 | METHOD get_packet_identifier. 51 | 52 | rv_packet_identifier = mv_packet_identifier. 53 | 54 | ENDMETHOD. 55 | 56 | 57 | METHOD get_return_codes. 58 | 59 | rt_return_codes = mt_return_codes. 60 | 61 | ENDMETHOD. 62 | 63 | 64 | METHOD set_packet_identifier. 65 | 66 | mv_packet_identifier = iv_packet_identifier. 67 | 68 | ENDMETHOD. 69 | 70 | 71 | METHOD set_return_codes. 72 | 73 | mt_return_codes = it_return_codes. 74 | 75 | ENDMETHOD. 76 | 77 | 78 | METHOD zif_mqtt_packet~decode. 79 | 80 | ASSERT io_stream->eat_hex( 1 ) = '90'. 81 | 82 | io_stream->eat_length( ). 83 | 84 | mv_packet_identifier = io_stream->eat_hex( 2 ). 85 | 86 | WHILE io_stream->get_length( ) > 0. 87 | APPEND io_stream->eat_hex( 1 ) TO mt_return_codes. 88 | ENDWHILE. 89 | 90 | ENDMETHOD. 91 | 92 | 93 | METHOD zif_mqtt_packet~encode. 94 | 95 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 96 | 97 | ASSERT NOT mv_packet_identifier IS INITIAL. 98 | lo_payload->add_hex( mv_packet_identifier ). 99 | 100 | LOOP AT mt_return_codes INTO DATA(lv_return_code). 101 | lo_payload->add_hex( lv_return_code ). 102 | ENDLOOP. 103 | 104 | ro_stream = NEW #( ). 105 | 106 | ro_stream->add_packet( 107 | ii_packet = me 108 | io_payload = lo_payload ). 109 | 110 | ENDMETHOD. 111 | 112 | 113 | METHOD zif_mqtt_packet~get_type. 114 | 115 | rv_value = zif_mqtt_constants=>gc_packets-suback. 116 | 117 | ENDMETHOD. 118 | ENDCLASS. 119 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_suback.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_suback. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE '9003000100'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_suback.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_SUBACK 7 | E 8 | SUBACK 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_subscribe.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_subscribe DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | TYPES: BEGIN OF ty_topic, 10 | topic TYPE zif_mqtt_packet=>ty_topic, 11 | qos TYPE zif_mqtt_packet=>ty_qos, 12 | END OF ty_topic. 13 | 14 | TYPES: 15 | ty_topics TYPE STANDARD TABLE OF ty_topic WITH EMPTY KEY . 16 | 17 | METHODS get_topics 18 | RETURNING 19 | VALUE(rt_topics) TYPE ty_topics . 20 | METHODS set_topics 21 | IMPORTING 22 | !it_topics TYPE ty_topics 23 | RETURNING 24 | VALUE(ro_subscribe) TYPE REF TO zcl_mqtt_packet_subscribe . 25 | METHODS constructor 26 | IMPORTING 27 | !it_topics TYPE ty_topics OPTIONAL 28 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 29 | METHODS get_packet_identifier 30 | RETURNING 31 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 32 | METHODS set_packet_identifier 33 | IMPORTING 34 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 35 | PROTECTED SECTION. 36 | 37 | DATA mt_topics TYPE ty_topics . 38 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 39 | PRIVATE SECTION. 40 | ENDCLASS. 41 | 42 | 43 | 44 | CLASS ZCL_MQTT_PACKET_SUBSCRIBE IMPLEMENTATION. 45 | 46 | 47 | METHOD constructor. 48 | 49 | mt_topics = it_topics. 50 | mv_packet_identifier = iv_packet_identifier. 51 | 52 | ENDMETHOD. 53 | 54 | 55 | METHOD get_packet_identifier. 56 | 57 | rv_packet_identifier = mv_packet_identifier. 58 | 59 | ENDMETHOD. 60 | 61 | 62 | METHOD get_topics. 63 | 64 | rt_topics = mt_topics. 65 | 66 | ENDMETHOD. 67 | 68 | 69 | METHOD set_packet_identifier. 70 | 71 | mv_packet_identifier = iv_packet_identifier. 72 | 73 | ENDMETHOD. 74 | 75 | 76 | METHOD set_topics. 77 | 78 | mt_topics = it_topics. 79 | 80 | ro_subscribe = me. 81 | 82 | ENDMETHOD. 83 | 84 | 85 | METHOD zif_mqtt_packet~decode. 86 | 87 | DATA: ls_topic LIKE LINE OF mt_topics. 88 | 89 | 90 | ASSERT io_stream->eat_hex( 1 ) = '82'. 91 | 92 | io_stream->eat_length( ). 93 | 94 | mv_packet_identifier = io_stream->eat_hex( 2 ). 95 | 96 | WHILE io_stream->get_length( ) > 0. 97 | ls_topic-topic = io_stream->eat_utf8( ). 98 | ls_topic-qos = io_stream->eat_hex( 1 ). 99 | APPEND ls_topic TO mt_topics. 100 | ENDWHILE. 101 | 102 | ENDMETHOD. 103 | 104 | 105 | METHOD zif_mqtt_packet~encode. 106 | 107 | ASSERT lines( mt_topics ) > 0. 108 | 109 | 110 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 111 | 112 | ASSERT NOT mv_packet_identifier IS INITIAL. 113 | lo_payload->add_hex( mv_packet_identifier ). 114 | 115 | LOOP AT mt_topics INTO DATA(ls_topic). 116 | lo_payload->add_utf8( ls_topic-topic ). 117 | lo_payload->add_hex( CONV xstring( ls_topic-qos ) ). 118 | ENDLOOP. 119 | 120 | ro_stream = NEW #( ). 121 | 122 | ro_stream->add_packet( 123 | ii_packet = me 124 | io_payload = lo_payload 125 | iv_flags = 2 ). 126 | 127 | ENDMETHOD. 128 | 129 | 130 | METHOD zif_mqtt_packet~get_type. 131 | 132 | rv_value = zif_mqtt_constants=>gc_packets-subscribe. 133 | 134 | ENDMETHOD. 135 | ENDCLASS. 136 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_subscribe.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_subscribe. 9 | 10 | METHODS: 11 | setup, 12 | encode FOR TESTING, 13 | test FOR TESTING. 14 | 15 | ENDCLASS. 16 | 17 | 18 | CLASS ltcl_test IMPLEMENTATION. 19 | 20 | METHOD setup. 21 | 22 | mo_cut = NEW #( ). 23 | 24 | ENDMETHOD. 25 | 26 | METHOD encode. 27 | 28 | mo_cut->set_topics( VALUE #( ( topic = |something| ) ) ). 29 | mo_cut->set_packet_identifier( '0001' ). 30 | 31 | DATA(lv_hex) = mo_cut->zif_mqtt_packet~encode( )->get_hex( ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = lv_hex 35 | exp = '820E00010009736F6D657468696E6700' ). 36 | 37 | ENDMETHOD. 38 | 39 | METHOD test. 40 | 41 | CONSTANTS: lc_hex TYPE xstring VALUE '820E00010009736F6D657468696E6700'. 42 | 43 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 44 | 45 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 46 | 47 | cl_abap_unit_assert=>assert_equals( 48 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 49 | exp = lc_hex ). 50 | 51 | ENDMETHOD. 52 | 53 | ENDCLASS. 54 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_subscribe.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_SUBSCRIBE 7 | E 8 | SUBSCRIBE 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_unsuback.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_unsuback DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS constructor 10 | IMPORTING 11 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 12 | METHODS get_packet_identifier 13 | RETURNING 14 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 15 | METHODS set_packet_identifier 16 | IMPORTING 17 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 18 | PROTECTED SECTION. 19 | 20 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 21 | PRIVATE SECTION. 22 | ENDCLASS. 23 | 24 | 25 | 26 | CLASS ZCL_MQTT_PACKET_UNSUBACK IMPLEMENTATION. 27 | 28 | 29 | METHOD constructor. 30 | 31 | mv_packet_identifier = iv_packet_identifier. 32 | 33 | ENDMETHOD. 34 | 35 | 36 | METHOD get_packet_identifier. 37 | 38 | rv_packet_identifier = mv_packet_identifier. 39 | 40 | ENDMETHOD. 41 | 42 | 43 | METHOD set_packet_identifier. 44 | 45 | mv_packet_identifier = iv_packet_identifier. 46 | 47 | ENDMETHOD. 48 | 49 | 50 | METHOD zif_mqtt_packet~decode. 51 | 52 | CONSTANTS: lc_header TYPE xstring VALUE 'B0'. 53 | 54 | ASSERT io_stream->eat_hex( 1 ) = lc_header. 55 | 56 | io_stream->eat_length( ). 57 | 58 | mv_packet_identifier = io_stream->eat_hex( 2 ). 59 | 60 | ENDMETHOD. 61 | 62 | 63 | METHOD zif_mqtt_packet~encode. 64 | 65 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 66 | 67 | ASSERT NOT mv_packet_identifier IS INITIAL. 68 | lo_payload->add_hex( mv_packet_identifier ). 69 | 70 | ro_stream = NEW #( ). 71 | 72 | ro_stream->add_packet( 73 | ii_packet = me 74 | io_payload = lo_payload ). 75 | 76 | ENDMETHOD. 77 | 78 | 79 | METHOD zif_mqtt_packet~get_type. 80 | 81 | rv_value = zif_mqtt_constants=>gc_packets-unsuback. 82 | 83 | ENDMETHOD. 84 | ENDCLASS. 85 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_unsuback.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_unsuback. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE 'B0020001'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 35 | exp = lc_hex ). 36 | 37 | ENDMETHOD. 38 | 39 | ENDCLASS. 40 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_unsuback.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_UNSUBACK 7 | E 8 | UNSUBACK 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_unsubscribe.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_packet_unsubscribe DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_packet . 8 | 9 | METHODS get_topics 10 | RETURNING 11 | VALUE(rt_topics) TYPE zif_mqtt_packet=>ty_topics_tt . 12 | METHODS set_topics 13 | IMPORTING 14 | !it_topics TYPE zif_mqtt_packet=>ty_topics_tt . 15 | METHODS constructor 16 | IMPORTING 17 | !it_topics TYPE zif_mqtt_packet=>ty_topics_tt OPTIONAL 18 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier OPTIONAL . 19 | METHODS get_packet_identifier 20 | RETURNING 21 | VALUE(rv_packet_identifier) TYPE zif_mqtt_packet=>ty_packet_identifier . 22 | METHODS set_packet_identifier 23 | IMPORTING 24 | !iv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 25 | PROTECTED SECTION. 26 | 27 | DATA mt_topics TYPE zif_mqtt_packet=>ty_topics_tt . 28 | DATA mv_packet_identifier TYPE zif_mqtt_packet=>ty_packet_identifier . 29 | PRIVATE SECTION. 30 | ENDCLASS. 31 | 32 | 33 | 34 | CLASS ZCL_MQTT_PACKET_UNSUBSCRIBE IMPLEMENTATION. 35 | 36 | 37 | METHOD constructor. 38 | 39 | mt_topics = it_topics. 40 | mv_packet_identifier = iv_packet_identifier. 41 | 42 | ENDMETHOD. 43 | 44 | 45 | METHOD get_packet_identifier. 46 | 47 | rv_packet_identifier = mv_packet_identifier. 48 | 49 | ENDMETHOD. 50 | 51 | 52 | METHOD get_topics. 53 | 54 | rt_topics = mt_topics. 55 | 56 | ENDMETHOD. 57 | 58 | 59 | METHOD set_packet_identifier. 60 | 61 | mv_packet_identifier = iv_packet_identifier. 62 | 63 | ENDMETHOD. 64 | 65 | 66 | METHOD set_topics. 67 | 68 | mt_topics = it_topics. 69 | 70 | ENDMETHOD. 71 | 72 | 73 | METHOD zif_mqtt_packet~decode. 74 | 75 | CONSTANTS: lc_header TYPE xstring VALUE 'A2'. 76 | 77 | ASSERT io_stream->eat_hex( 1 ) = lc_header. 78 | 79 | io_stream->eat_length( ). 80 | 81 | mv_packet_identifier = io_stream->eat_hex( 2 ). 82 | 83 | WHILE io_stream->get_length( ) > 0. 84 | APPEND io_stream->eat_utf8( ) TO mt_topics. 85 | ENDWHILE. 86 | 87 | ASSERT lines( mt_topics ) > 0. 88 | 89 | ENDMETHOD. 90 | 91 | 92 | METHOD zif_mqtt_packet~encode. 93 | 94 | DATA(lo_payload) = NEW zcl_mqtt_stream( ). 95 | 96 | ASSERT NOT mv_packet_identifier IS INITIAL. 97 | lo_payload->add_hex( mv_packet_identifier ). 98 | 99 | ASSERT lines( mt_topics ) > 0. 100 | LOOP AT mt_topics INTO DATA(lv_topic). 101 | lo_payload->add_utf8( lv_topic ). 102 | ENDLOOP. 103 | 104 | ro_stream = NEW #( ). 105 | 106 | ro_stream->add_packet( 107 | ii_packet = me 108 | iv_flags = 2 109 | io_payload = lo_payload ). 110 | 111 | ENDMETHOD. 112 | 113 | 114 | METHOD zif_mqtt_packet~get_type. 115 | 116 | rv_value = zif_mqtt_constants=>gc_packets-unsubscribe. 117 | 118 | ENDMETHOD. 119 | ENDCLASS. 120 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_unsubscribe.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_test DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_packet_unsubscribe. 9 | 10 | METHODS: 11 | setup, 12 | test FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | 17 | CLASS ltcl_test IMPLEMENTATION. 18 | 19 | METHOD setup. 20 | 21 | mo_cut = NEW #( ). 22 | 23 | ENDMETHOD. 24 | 25 | METHOD test. 26 | 27 | CONSTANTS: lc_hex TYPE xstring VALUE 'A20A00010006666F6F626172'. 28 | 29 | DATA(lo_stream) = NEW zcl_mqtt_stream( lc_hex ). 30 | 31 | mo_cut->zif_mqtt_packet~decode( lo_stream ). 32 | 33 | cl_abap_unit_assert=>assert_equals( 34 | act = mo_cut->get_topics( ) 35 | exp = VALUE zif_mqtt_packet=>ty_topics_tt( ( |foobar| ) ) ). 36 | 37 | cl_abap_unit_assert=>assert_equals( 38 | act = mo_cut->zif_mqtt_packet~encode( )->get_hex( ) 39 | exp = lc_hex ). 40 | 41 | ENDMETHOD. 42 | 43 | ENDCLASS. 44 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_packet_unsubscribe.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_PACKET_UNSUBSCRIBE 7 | E 8 | UNSUBSCRIBE 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_stream.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_stream DEFINITION 2 | PUBLIC 3 | CREATE PUBLIC . 4 | 5 | PUBLIC SECTION. 6 | 7 | METHODS add_hex 8 | IMPORTING 9 | !iv_hex TYPE xsequence 10 | RETURNING 11 | VALUE(ro_stream) TYPE REF TO zcl_mqtt_stream . 12 | METHODS add_length 13 | IMPORTING 14 | !iv_length TYPE i . 15 | METHODS add_packet 16 | IMPORTING 17 | !ii_packet TYPE REF TO zif_mqtt_packet 18 | !io_payload TYPE REF TO zcl_mqtt_stream OPTIONAL 19 | !iv_flags TYPE i DEFAULT 0 20 | RETURNING 21 | VALUE(ro_stream) TYPE REF TO zcl_mqtt_stream . 22 | METHODS add_stream 23 | IMPORTING 24 | !io_stream TYPE REF TO zcl_mqtt_stream . 25 | METHODS add_utf8 26 | IMPORTING 27 | !iv_string TYPE csequence 28 | RETURNING 29 | VALUE(ro_stream) TYPE REF TO zcl_mqtt_stream . 30 | METHODS constructor 31 | IMPORTING 32 | !iv_hex TYPE xsequence OPTIONAL . 33 | METHODS eat_hex 34 | IMPORTING 35 | !iv_length TYPE i 36 | RETURNING 37 | VALUE(rv_hex) TYPE xstring . 38 | METHODS eat_length 39 | RETURNING 40 | VALUE(rv_length) TYPE i . 41 | METHODS eat_packet 42 | RETURNING 43 | VALUE(ri_packet) TYPE REF TO zif_mqtt_packet . 44 | METHODS eat_utf8 45 | RETURNING 46 | VALUE(rv_string) TYPE string . 47 | METHODS get_hex 48 | RETURNING 49 | VALUE(rv_hex) TYPE xstring . 50 | METHODS get_length 51 | RETURNING 52 | VALUE(rv_length) TYPE i . 53 | METHODS peek_hex 54 | IMPORTING 55 | !iv_length TYPE i 56 | RETURNING 57 | VALUE(rv_hex) TYPE xstring . 58 | PROTECTED SECTION. 59 | 60 | DATA mv_hex TYPE xstring . 61 | PRIVATE SECTION. 62 | ENDCLASS. 63 | 64 | 65 | 66 | CLASS ZCL_MQTT_STREAM IMPLEMENTATION. 67 | 68 | 69 | METHOD add_hex. 70 | 71 | CONCATENATE mv_hex iv_hex INTO mv_hex IN BYTE MODE. 72 | 73 | ro_stream = me. 74 | 75 | ENDMETHOD. 76 | 77 | 78 | METHOD add_length. 79 | 80 | DATA: lv_length LIKE iv_length, 81 | lv_byte TYPE x. 82 | 83 | 84 | ASSERT iv_length >= 0. 85 | 86 | lv_length = iv_length. 87 | WHILE lv_length > 0. 88 | lv_byte = lv_length MOD 128. 89 | 90 | lv_length = lv_length DIV 128. 91 | IF lv_length > 0. 92 | lv_byte = lv_byte + 128. 93 | ENDIF. 94 | 95 | add_hex( lv_byte ). 96 | ENDWHILE. 97 | 98 | IF iv_length = 0. 99 | add_hex( '00' ). 100 | ENDIF. 101 | 102 | ENDMETHOD. 103 | 104 | 105 | METHOD add_packet. 106 | 107 | DATA: lv_byte TYPE x, 108 | lv_length TYPE i. 109 | 110 | lv_byte = ii_packet->get_type( ) * 16 + iv_flags. 111 | 112 | add_hex( lv_byte ). 113 | 114 | IF io_payload IS SUPPLIED. 115 | lv_length = io_payload->get_length( ). 116 | ENDIF. 117 | add_length( lv_length ). 118 | 119 | IF io_payload IS SUPPLIED. 120 | add_stream( io_payload ). 121 | ENDIF. 122 | 123 | ro_stream = me. 124 | 125 | ENDMETHOD. 126 | 127 | 128 | METHOD add_stream. 129 | 130 | DATA: lv_hex TYPE xstring. 131 | 132 | 133 | lv_hex = io_stream->get_hex( ). 134 | 135 | CONCATENATE mv_hex lv_hex INTO mv_hex IN BYTE MODE. 136 | 137 | ENDMETHOD. 138 | 139 | 140 | METHOD add_utf8. 141 | 142 | DATA: lv_len TYPE x LENGTH 2. 143 | 144 | 145 | DATA(lv_hex) = cl_binary_convert=>string_to_xstring_utf8( iv_string ). 146 | 147 | lv_len = xstrlen( lv_hex ). 148 | 149 | CONCATENATE mv_hex lv_len lv_hex INTO mv_hex IN BYTE MODE. 150 | 151 | ro_stream = me. 152 | 153 | ENDMETHOD. 154 | 155 | 156 | METHOD constructor. 157 | 158 | IF iv_hex IS SUPPLIED. 159 | mv_hex = iv_hex. 160 | ENDIF. 161 | 162 | ENDMETHOD. 163 | 164 | 165 | METHOD eat_hex. 166 | 167 | rv_hex = mv_hex(iv_length). 168 | 169 | mv_hex = mv_hex+iv_length. 170 | 171 | ENDMETHOD. 172 | 173 | 174 | METHOD eat_length. 175 | 176 | DATA: lv_byte TYPE x LENGTH 1, 177 | lv_multiplier TYPE i VALUE 1. 178 | 179 | 180 | DO. 181 | ASSERT sy-index <= 4. 182 | 183 | lv_byte = eat_hex( 1 ). 184 | 185 | rv_length = rv_length + ( lv_byte MOD 128 ) * lv_multiplier. 186 | lv_multiplier = lv_multiplier * 128. 187 | 188 | IF lv_byte < 128. 189 | EXIT. 190 | ENDIF. 191 | ENDDO. 192 | 193 | ENDMETHOD. 194 | 195 | 196 | METHOD eat_packet. 197 | 198 | DATA: lv_int TYPE i. 199 | 200 | 201 | lv_int = peek_hex( 1 ) / 16. 202 | 203 | CASE lv_int. 204 | WHEN zif_mqtt_constants=>gc_packets-connect. 205 | ri_packet = NEW zcl_mqtt_packet_connect( ). 206 | WHEN zif_mqtt_constants=>gc_packets-connack. 207 | ri_packet = NEW zcl_mqtt_packet_connack( ). 208 | WHEN zif_mqtt_constants=>gc_packets-publish. 209 | ri_packet = NEW zcl_mqtt_packet_publish( ). 210 | WHEN zif_mqtt_constants=>gc_packets-puback. 211 | ri_packet = NEW zcl_mqtt_packet_puback( ). 212 | WHEN zif_mqtt_constants=>gc_packets-pubrec. 213 | ri_packet = NEW zcl_mqtt_packet_pubrec( ). 214 | WHEN zif_mqtt_constants=>gc_packets-pubrel. 215 | ri_packet = NEW zcl_mqtt_packet_pubrel( ). 216 | WHEN zif_mqtt_constants=>gc_packets-pubcomp. 217 | ri_packet = NEW zcl_mqtt_packet_pubcomp( ). 218 | WHEN zif_mqtt_constants=>gc_packets-subscribe. 219 | ri_packet = NEW zcl_mqtt_packet_subscribe( ). 220 | WHEN zif_mqtt_constants=>gc_packets-suback. 221 | ri_packet = NEW zcl_mqtt_packet_suback( ). 222 | WHEN zif_mqtt_constants=>gc_packets-unsubscribe. 223 | ri_packet = NEW zcl_mqtt_packet_unsubscribe( ). 224 | WHEN zif_mqtt_constants=>gc_packets-unsuback. 225 | ri_packet = NEW zcl_mqtt_packet_unsuback( ). 226 | WHEN zif_mqtt_constants=>gc_packets-pingreq. 227 | ri_packet = NEW zcl_mqtt_packet_pingreq( ). 228 | WHEN zif_mqtt_constants=>gc_packets-pingresp. 229 | ri_packet = NEW zcl_mqtt_packet_pingresp( ). 230 | WHEN zif_mqtt_constants=>gc_packets-disconnect. 231 | ri_packet = NEW zcl_mqtt_packet_disconnect( ). 232 | WHEN OTHERS. 233 | ASSERT 0 = 1. 234 | ENDCASE. 235 | 236 | ri_packet->decode( me ). 237 | 238 | ENDMETHOD. 239 | 240 | 241 | METHOD eat_utf8. 242 | 243 | DATA: lv_len TYPE x LENGTH 2, 244 | lv_int TYPE i. 245 | 246 | 247 | lv_len = eat_hex( 2 ). 248 | lv_int = lv_len. 249 | 250 | rv_string = cl_binary_convert=>xstring_utf8_to_string( eat_hex( lv_int ) ). 251 | 252 | ENDMETHOD. 253 | 254 | 255 | METHOD get_hex. 256 | 257 | rv_hex = mv_hex. 258 | 259 | ENDMETHOD. 260 | 261 | 262 | METHOD get_length. 263 | 264 | rv_length = xstrlen( mv_hex ). 265 | 266 | ENDMETHOD. 267 | 268 | 269 | METHOD peek_hex. 270 | 271 | rv_hex = mv_hex(iv_length). 272 | 273 | ENDMETHOD. 274 | ENDCLASS. 275 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_stream.clas.testclasses.abap: -------------------------------------------------------------------------------- 1 | 2 | CLASS ltcl_eat_packet DEFINITION FOR TESTING 3 | DURATION SHORT 4 | RISK LEVEL HARMLESS FINAL. 5 | 6 | PRIVATE SECTION. 7 | DATA: 8 | mo_cut TYPE REF TO zcl_mqtt_stream. 9 | 10 | METHODS: 11 | setup, 12 | connack FOR TESTING. 13 | 14 | ENDCLASS. 15 | 16 | CLASS ltcl_eat_packet IMPLEMENTATION. 17 | 18 | METHOD setup. 19 | mo_cut = NEW #( ). 20 | ENDMETHOD. 21 | 22 | METHOD connack. 23 | 24 | DATA(li_packet) = mo_cut->add_hex( '20020000' )->eat_packet( ). 25 | 26 | cl_abap_unit_assert=>assert_equals( 27 | act = li_packet->get_type( ) 28 | exp = zif_mqtt_constants=>gc_packets-connack ). 29 | 30 | ENDMETHOD. 31 | 32 | ENDCLASS. 33 | 34 | 35 | CLASS ltcl_stream DEFINITION FOR TESTING 36 | DURATION SHORT 37 | RISK LEVEL HARMLESS FINAL. 38 | 39 | PRIVATE SECTION. 40 | DATA: 41 | mo_cut TYPE REF TO zcl_mqtt_stream. 42 | 43 | METHODS: 44 | setup, 45 | utf8 FOR TESTING, 46 | peek FOR TESTING, 47 | add_n_eat FOR TESTING. 48 | 49 | ENDCLASS. 50 | 51 | 52 | CLASS ltcl_stream IMPLEMENTATION. 53 | 54 | METHOD setup. 55 | mo_cut = NEW #( ). 56 | ENDMETHOD. 57 | 58 | METHOD peek. 59 | 60 | CONSTANTS: lc_hex TYPE xstring VALUE '12'. 61 | 62 | mo_cut->add_hex( lc_hex ). 63 | 64 | cl_abap_unit_assert=>assert_equals( 65 | act = mo_cut->peek_hex( 1 ) 66 | exp = lc_hex ). 67 | 68 | cl_abap_unit_assert=>assert_equals( 69 | act = mo_cut->get_length( ) 70 | exp = 1 ). 71 | 72 | ENDMETHOD. 73 | 74 | METHOD utf8. 75 | 76 | CONSTANTS: lc_str TYPE string VALUE 'MQTT'. 77 | 78 | DATA(lv_hex) = mo_cut->add_utf8( lc_str )->get_hex( ). 79 | 80 | cl_abap_unit_assert=>assert_equals( 81 | act = lv_hex 82 | exp = '00044D515454' ). 83 | 84 | DATA(lv_str) = mo_cut->eat_utf8( ). 85 | 86 | cl_abap_unit_assert=>assert_equals( 87 | act = lv_str 88 | exp = lc_str ). 89 | 90 | ENDMETHOD. 91 | 92 | METHOD add_n_eat. 93 | 94 | CONSTANTS: lc_hex TYPE xstring VALUE '1122'. 95 | 96 | mo_cut->add_hex( lc_hex ). 97 | 98 | cl_abap_unit_assert=>assert_equals( 99 | act = mo_cut->get_length( ) 100 | exp = 2 ). 101 | 102 | cl_abap_unit_assert=>assert_equals( 103 | act = mo_cut->eat_hex( 2 ) 104 | exp = lc_hex ). 105 | 106 | cl_abap_unit_assert=>assert_equals( 107 | act = mo_cut->get_length( ) 108 | exp = 0 ). 109 | 110 | ENDMETHOD. 111 | 112 | ENDCLASS. 113 | 114 | 115 | CLASS ltcl_length DEFINITION FOR TESTING 116 | DURATION SHORT 117 | RISK LEVEL HARMLESS FINAL. 118 | 119 | PRIVATE SECTION. 120 | DATA: 121 | mo_cut TYPE REF TO zcl_mqtt_stream. 122 | 123 | METHODS: 124 | setup, 125 | test IMPORTING iv_hex TYPE xstring 126 | iv_length TYPE i, 127 | test01 FOR TESTING, 128 | test02 FOR TESTING, 129 | test03 FOR TESTING, 130 | test04 FOR TESTING, 131 | test05 FOR TESTING, 132 | test06 FOR TESTING. 133 | 134 | ENDCLASS. 135 | 136 | CLASS ltcl_length IMPLEMENTATION. 137 | 138 | METHOD setup. 139 | mo_cut = NEW #( ). 140 | ENDMETHOD. 141 | 142 | METHOD test. 143 | 144 | DATA(lv_length) = mo_cut->add_hex( iv_hex )->eat_length( ). 145 | 146 | cl_abap_unit_assert=>assert_equals( 147 | act = lv_length 148 | exp = iv_length ). 149 | 150 | cl_abap_unit_assert=>assert_equals( 151 | act = mo_cut->get_length( ) 152 | exp = 0 ). 153 | 154 | mo_cut->add_length( iv_length ). 155 | 156 | cl_abap_unit_assert=>assert_equals( 157 | act = mo_cut->get_hex( ) 158 | exp = iv_hex ). 159 | 160 | ENDMETHOD. 161 | 162 | METHOD test01. 163 | 164 | test( iv_hex = '02' 165 | iv_length = 2 ). 166 | 167 | ENDMETHOD. 168 | 169 | METHOD test02. 170 | 171 | test( iv_hex = '8610' 172 | iv_length = 2054 ). 173 | 174 | ENDMETHOD. 175 | 176 | METHOD test03. 177 | 178 | test( iv_hex = '86808001' 179 | iv_length = 2097158 ). 180 | 181 | ENDMETHOD. 182 | 183 | METHOD test04. 184 | 185 | test( iv_hex = '80808001' 186 | iv_length = 2097152 ). 187 | 188 | ENDMETHOD. 189 | 190 | METHOD test05. 191 | 192 | test( iv_hex = '7F' 193 | iv_length = 127 ). 194 | 195 | ENDMETHOD. 196 | 197 | METHOD test06. 198 | 199 | test( iv_hex = '00' 200 | iv_length = 0 ). 201 | 202 | ENDMETHOD. 203 | 204 | ENDCLASS. 205 | -------------------------------------------------------------------------------- /src/mqtt/packets/zcl_mqtt_stream.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_STREAM 7 | E 8 | Stream 9 | 1 10 | X 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/mqtt/packets/zif_mqtt_packet.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_mqtt_packet PUBLIC . 2 | 3 | TYPES ty_qos TYPE i . 4 | TYPES: 5 | ty_packet_identifier TYPE x LENGTH 2 . 6 | TYPES ty_topic TYPE string . 7 | TYPES: 8 | BEGIN OF ty_message, 9 | topic TYPE ty_topic, 10 | message TYPE xstring, 11 | END OF ty_message . 12 | TYPES: 13 | ty_topics_tt TYPE STANDARD TABLE OF ty_topic WITH EMPTY KEY . 14 | 15 | CONSTANTS: 16 | BEGIN OF gc_qos, 17 | at_most_once TYPE ty_qos VALUE 0, 18 | at_least_once TYPE ty_qos VALUE 1, 19 | exactly_once TYPE ty_qos VALUE 2, 20 | END OF gc_qos . 21 | 22 | METHODS get_type 23 | RETURNING 24 | VALUE(rv_value) TYPE i . 25 | METHODS encode 26 | RETURNING 27 | VALUE(ro_stream) TYPE REF TO zcl_mqtt_stream . 28 | METHODS decode 29 | IMPORTING 30 | !io_stream TYPE REF TO zcl_mqtt_stream . 31 | ENDINTERFACE. 32 | -------------------------------------------------------------------------------- /src/mqtt/packets/zif_mqtt_packet.intf.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZIF_MQTT_PACKET 7 | E 8 | Packet 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/mqtt/zcl_mqtt_transport_tcp.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_transport_tcp DEFINITION 2 | PUBLIC 3 | CREATE PROTECTED . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_transport . 8 | INTERFACES if_apc_wsp_event_handler . 9 | INTERFACES if_apc_wsp_event_handler_base . 10 | 11 | CLASS-METHODS create 12 | IMPORTING 13 | !iv_host TYPE string 14 | !iv_port TYPE string 15 | iv_protocol TYPE i DEFAULT cl_apc_tcp_client_manager=>co_protocol_type_tcp 16 | RETURNING 17 | VALUE(ri_transport) TYPE REF TO zif_mqtt_transport 18 | RAISING 19 | cx_apc_error . 20 | PROTECTED SECTION. 21 | 22 | TYPES: 23 | ty_byte TYPE x LENGTH 1 . 24 | 25 | DATA: 26 | BEGIN OF ms_message, 27 | received TYPE abap_bool, 28 | message TYPE x LENGTH 1, 29 | END OF ms_message . 30 | DATA mi_client TYPE REF TO if_apc_wsp_client . 31 | 32 | METHODS receive_byte 33 | IMPORTING 34 | !iv_timeout TYPE i 35 | RETURNING 36 | VALUE(rv_byte) TYPE ty_byte 37 | RAISING 38 | zcx_mqtt_timeout . 39 | PRIVATE SECTION. 40 | ENDCLASS. 41 | 42 | 43 | 44 | CLASS ZCL_MQTT_TRANSPORT_TCP IMPLEMENTATION. 45 | 46 | 47 | METHOD create. 48 | 49 | DATA(lo_tcp) = NEW zcl_mqtt_transport_tcp( ). 50 | 51 | DATA(ls_frame) = VALUE apc_tcp_frame( 52 | frame_type = if_apc_tcp_frame_types=>co_frame_type_fixed_length 53 | fixed_length = 1 ). 54 | 55 | lo_tcp->mi_client = cl_apc_tcp_client_manager=>create( 56 | i_protocol = iv_protocol 57 | i_host = iv_host 58 | i_port = iv_port 59 | i_frame = ls_frame 60 | i_event_handler = lo_tcp ). 61 | 62 | ri_transport ?= lo_tcp. 63 | 64 | ENDMETHOD. 65 | 66 | 67 | METHOD if_apc_wsp_event_handler~on_close. 68 | 69 | * todo? 70 | RETURN. 71 | 72 | ENDMETHOD. 73 | 74 | 75 | METHOD if_apc_wsp_event_handler~on_error. 76 | 77 | * todo? 78 | RETURN. 79 | 80 | ENDMETHOD. 81 | 82 | 83 | METHOD if_apc_wsp_event_handler~on_message. 84 | 85 | ms_message-received = abap_true. 86 | TRY. 87 | ms_message-message = i_message->get_binary( ). 88 | CATCH cx_apc_error. 89 | ASSERT 0 = 1. " todo 90 | ENDTRY. 91 | 92 | ENDMETHOD. 93 | 94 | 95 | METHOD if_apc_wsp_event_handler~on_open. 96 | 97 | RETURN. 98 | 99 | ENDMETHOD. 100 | 101 | 102 | METHOD receive_byte. 103 | 104 | CLEAR ms_message. 105 | WAIT FOR PUSH CHANNELS UNTIL ms_message IS NOT INITIAL UP TO iv_timeout SECONDS. 106 | IF sy-subrc = 0. 107 | rv_byte = ms_message-message. 108 | ELSE. 109 | RAISE EXCEPTION TYPE zcx_mqtt_timeout. 110 | ENDIF. 111 | 112 | ENDMETHOD. 113 | 114 | 115 | METHOD zif_mqtt_transport~connect. 116 | 117 | mi_client->connect( ). 118 | 119 | ENDMETHOD. 120 | 121 | 122 | METHOD zif_mqtt_transport~disconnect. 123 | 124 | mi_client->close( ). 125 | 126 | ENDMETHOD. 127 | 128 | 129 | METHOD zif_mqtt_transport~listen. 130 | 131 | DATA: lv_length TYPE i, 132 | lv_multiplier TYPE i VALUE 1. 133 | 134 | 135 | DATA(lo_stream) = NEW zcl_mqtt_stream( ). 136 | 137 | DATA(lv_byte) = receive_byte( iv_timeout ). 138 | lo_stream->add_hex( lv_byte ). 139 | 140 | DO. 141 | ASSERT sy-index <= 4. 142 | 143 | lv_byte = receive_byte( iv_timeout ). 144 | lo_stream->add_hex( lv_byte ). 145 | 146 | lv_length = lv_length + ( lv_byte MOD 128 ) * lv_multiplier. 147 | lv_multiplier = lv_multiplier * 128. 148 | 149 | IF lv_byte < 128. 150 | EXIT. 151 | ENDIF. 152 | ENDDO. 153 | 154 | DO lv_length TIMES. 155 | lv_byte = receive_byte( iv_timeout ). 156 | lo_stream->add_hex( lv_byte ). 157 | ENDDO. 158 | 159 | ri_packet = lo_stream->eat_packet( ). 160 | 161 | ENDMETHOD. 162 | 163 | 164 | METHOD zif_mqtt_transport~send. 165 | 166 | DATA: li_msgmgr TYPE REF TO if_apc_wsp_message_manager. 167 | 168 | li_msgmgr ?= mi_client->get_message_manager( ). 169 | DATA(li_message) = li_msgmgr->create_message( ). 170 | 171 | DATA(lv_hex) = ii_packet->encode( )->get_hex( ). 172 | 173 | WHILE xstrlen( lv_hex ) > 0. 174 | DATA(lv_single) = lv_hex(1). 175 | li_message->set_binary( lv_single ). 176 | li_msgmgr->send( li_message ). 177 | lv_hex = lv_hex+1. 178 | ENDWHILE. 179 | 180 | ENDMETHOD. 181 | ENDCLASS. 182 | -------------------------------------------------------------------------------- /src/mqtt/zcl_mqtt_transport_tcp.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_TRANSPORT_TCP 7 | E 8 | TCP 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | ZCL_MQTT_TRANSPORT_TCP 17 | MI_CLIENT 18 | E 19 | APC framework: WebSocket client interface (do not implement) 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/mqtt/zcl_mqtt_transport_ws.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_mqtt_transport_ws DEFINITION 2 | PUBLIC 3 | CREATE PROTECTED . 4 | 5 | PUBLIC SECTION. 6 | 7 | INTERFACES zif_mqtt_transport . 8 | INTERFACES if_apc_wsp_event_handler . 9 | INTERFACES if_apc_wsp_event_handler_base . 10 | 11 | CLASS-METHODS create_by_url 12 | IMPORTING 13 | !iv_url TYPE string 14 | RETURNING 15 | VALUE(ri_transport) TYPE REF TO zif_mqtt_transport 16 | RAISING 17 | cx_apc_error . 18 | PROTECTED SECTION. 19 | 20 | DATA mi_client TYPE REF TO if_apc_wsp_client . 21 | 22 | DATA: BEGIN OF ms_message, 23 | received TYPE abap_bool, 24 | message TYPE xstring, 25 | END OF ms_message. 26 | PRIVATE SECTION. 27 | ENDCLASS. 28 | 29 | 30 | 31 | CLASS ZCL_MQTT_TRANSPORT_WS IMPLEMENTATION. 32 | 33 | 34 | METHOD create_by_url. 35 | 36 | DATA(lo_ws) = NEW zcl_mqtt_transport_ws( ). 37 | 38 | lo_ws->mi_client = cl_apc_wsp_client_manager=>create_by_url( 39 | i_url = iv_url 40 | i_protocol = if_apc_wsp_event_handler=>co_event_handler_type 41 | i_event_handler = lo_ws ). 42 | 43 | ri_transport ?= lo_ws. 44 | 45 | ENDMETHOD. 46 | 47 | 48 | METHOD if_apc_wsp_event_handler~on_close. 49 | 50 | * todo? 51 | RETURN. 52 | 53 | ENDMETHOD. 54 | 55 | 56 | METHOD if_apc_wsp_event_handler~on_error. 57 | 58 | * todo? 59 | RETURN. 60 | 61 | ENDMETHOD. 62 | 63 | 64 | METHOD if_apc_wsp_event_handler~on_message. 65 | 66 | ms_message-received = abap_true. 67 | TRY. 68 | ms_message-message = i_message->get_binary( ). 69 | CATCH cx_apc_error. 70 | ASSERT 0 = 1. " todo 71 | ENDTRY. 72 | 73 | ENDMETHOD. 74 | 75 | 76 | METHOD if_apc_wsp_event_handler~on_open. 77 | 78 | RETURN. 79 | 80 | ENDMETHOD. 81 | 82 | 83 | METHOD zif_mqtt_transport~connect. 84 | 85 | mi_client->connect( ). 86 | 87 | ENDMETHOD. 88 | 89 | 90 | METHOD zif_mqtt_transport~disconnect. 91 | 92 | mi_client->close( ). 93 | 94 | ENDMETHOD. 95 | 96 | 97 | METHOD zif_mqtt_transport~listen. 98 | 99 | CLEAR ms_message. 100 | WAIT FOR PUSH CHANNELS UNTIL ms_message IS NOT INITIAL UP TO iv_timeout SECONDS. 101 | IF sy-subrc = 0. 102 | ri_packet = NEW zcl_mqtt_stream( ms_message-message )->eat_packet( ). 103 | ELSE. 104 | RAISE EXCEPTION TYPE zcx_mqtt_timeout. 105 | ENDIF. 106 | 107 | ENDMETHOD. 108 | 109 | 110 | METHOD zif_mqtt_transport~send. 111 | 112 | DATA: li_msgmgr TYPE REF TO if_apc_wsp_message_manager. 113 | 114 | li_msgmgr ?= mi_client->get_message_manager( ). 115 | 116 | DATA(li_message) = li_msgmgr->create_message( ). 117 | li_message->set_binary( ii_packet->encode( )->get_hex( ) ). 118 | li_msgmgr->send( li_message ). 119 | 120 | ENDMETHOD. 121 | ENDCLASS. 122 | -------------------------------------------------------------------------------- /src/mqtt/zcl_mqtt_transport_ws.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCL_MQTT_TRANSPORT_WS 7 | E 8 | Websockets 9 | 1 10 | X 11 | X 12 | X 13 | 14 | 15 | 16 | ZCL_MQTT_TRANSPORT_WS 17 | MI_CLIENT 18 | E 19 | APC framework: WebSocket client interface (do not implement) 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/mqtt/zcx_mqtt.clas.abap: -------------------------------------------------------------------------------- 1 | class ZCX_MQTT definition 2 | public 3 | inheriting from CX_STATIC_CHECK 4 | abstract 5 | create public . 6 | 7 | public section. 8 | 9 | interfaces IF_T100_DYN_MSG . 10 | interfaces IF_T100_MESSAGE . 11 | 12 | methods CONSTRUCTOR 13 | importing 14 | !TEXTID like IF_T100_MESSAGE=>T100KEY optional 15 | !PREVIOUS like PREVIOUS optional . 16 | protected section. 17 | private section. 18 | ENDCLASS. 19 | 20 | 21 | 22 | CLASS ZCX_MQTT IMPLEMENTATION. 23 | 24 | 25 | method CONSTRUCTOR. 26 | CALL METHOD SUPER->CONSTRUCTOR 27 | EXPORTING 28 | PREVIOUS = PREVIOUS 29 | . 30 | clear me->textid. 31 | if textid is initial. 32 | IF_T100_MESSAGE~T100KEY = IF_T100_MESSAGE=>DEFAULT_TEXTID. 33 | else. 34 | IF_T100_MESSAGE~T100KEY = TEXTID. 35 | endif. 36 | endmethod. 37 | ENDCLASS. 38 | -------------------------------------------------------------------------------- /src/mqtt/zcx_mqtt.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCX_MQTT 7 | E 8 | Abstract Exception 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | ZCX_MQTT 18 | CONSTRUCTOR 19 | E 20 | CONSTRUCTOR 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/mqtt/zcx_mqtt_timeout.clas.abap: -------------------------------------------------------------------------------- 1 | class ZCX_MQTT_TIMEOUT definition 2 | public 3 | inheriting from ZCX_MQTT 4 | create public . 5 | 6 | public section. 7 | 8 | methods CONSTRUCTOR 9 | importing 10 | !TEXTID like IF_T100_MESSAGE=>T100KEY optional 11 | !PREVIOUS like PREVIOUS optional . 12 | protected section. 13 | private section. 14 | ENDCLASS. 15 | 16 | 17 | 18 | CLASS ZCX_MQTT_TIMEOUT IMPLEMENTATION. 19 | 20 | 21 | method CONSTRUCTOR. 22 | CALL METHOD SUPER->CONSTRUCTOR 23 | EXPORTING 24 | PREVIOUS = PREVIOUS 25 | . 26 | clear me->textid. 27 | if textid is initial. 28 | IF_T100_MESSAGE~T100KEY = IF_T100_MESSAGE=>DEFAULT_TEXTID. 29 | else. 30 | IF_T100_MESSAGE~T100KEY = TEXTID. 31 | endif. 32 | endmethod. 33 | ENDCLASS. 34 | -------------------------------------------------------------------------------- /src/mqtt/zcx_mqtt_timeout.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCX_MQTT_TIMEOUT 7 | E 8 | Timeout 9 | 40 10 | 1 11 | X 12 | X 13 | X 14 | 15 | 16 | 17 | ZCX_MQTT_TIMEOUT 18 | CONSTRUCTOR 19 | E 20 | CONSTRUCTOR 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/mqtt/zif_mqtt_constants.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_mqtt_constants 2 | PUBLIC . 3 | 4 | 5 | CONSTANTS: BEGIN OF gc_packets, 6 | connect TYPE i VALUE 1, 7 | connack TYPE i VALUE 2, 8 | publish TYPE i VALUE 3, 9 | puback TYPE i VALUE 4, 10 | pubrec TYPE i VALUE 5, 11 | pubrel TYPE i VALUE 6, 12 | pubcomp TYPE i VALUE 7, 13 | subscribe TYPE i VALUE 8, 14 | suback TYPE i VALUE 9, 15 | unsubscribe TYPE i VALUE 10, 16 | unsuback TYPE i VALUE 11, 17 | pingreq TYPE i VALUE 12, 18 | pingresp TYPE i VALUE 13, 19 | disconnect TYPE i VALUE 14, 20 | END OF gc_packets. 21 | 22 | ENDINTERFACE. 23 | -------------------------------------------------------------------------------- /src/mqtt/zif_mqtt_constants.intf.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZIF_MQTT_CONSTANTS 7 | E 8 | Constants 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/mqtt/zif_mqtt_transport.intf.abap: -------------------------------------------------------------------------------- 1 | INTERFACE zif_mqtt_transport PUBLIC. 2 | 3 | 4 | METHODS connect 5 | RAISING 6 | cx_apc_error . 7 | METHODS disconnect 8 | RAISING 9 | cx_apc_error . 10 | METHODS send 11 | IMPORTING 12 | !ii_packet TYPE REF TO zif_mqtt_packet 13 | RAISING 14 | zcx_mqtt 15 | cx_apc_error . 16 | METHODS listen 17 | IMPORTING 18 | !iv_timeout TYPE i 19 | RETURNING 20 | VALUE(ri_packet) TYPE REF TO zif_mqtt_packet 21 | RAISING 22 | zcx_mqtt . 23 | ENDINTERFACE. 24 | -------------------------------------------------------------------------------- /src/mqtt/zif_mqtt_transport.intf.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZIF_MQTT_TRANSPORT 7 | E 8 | Transport 9 | 2 10 | 1 11 | X 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | abapMQ 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/test/package.devc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Test 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/test/zabapmq_http_client.prog.abap: -------------------------------------------------------------------------------- 1 | REPORT zabapmq_http_client. 2 | 3 | PARAMETERS: p_host TYPE text200 DEFAULT 'google.com'. 4 | 5 | CLASS lcl_apc_handler DEFINITION 6 | FINAL 7 | CREATE PUBLIC. 8 | 9 | PUBLIC SECTION. 10 | INTERFACES: if_apc_wsp_event_handler. 11 | DATA: mv_message TYPE string. 12 | 13 | ENDCLASS. 14 | 15 | CLASS lcl_apc_handler IMPLEMENTATION. 16 | METHOD if_apc_wsp_event_handler~on_open. 17 | RETURN. 18 | ENDMETHOD. 19 | 20 | METHOD if_apc_wsp_event_handler~on_message. 21 | "message handling 22 | TRY. 23 | mv_message = i_message->get_text( ). 24 | CATCH cx_apc_error INTO DATA(lx_apc_error). 25 | mv_message = 'foo' && lx_apc_error->get_text( ). 26 | ENDTRY. 27 | ENDMETHOD. 28 | 29 | METHOD if_apc_wsp_event_handler~on_close. 30 | "close handling 31 | mv_message = 'Connection closed !'(001). 32 | ENDMETHOD. 33 | 34 | METHOD if_apc_wsp_event_handler~on_error. 35 | "error/close handling 36 | RETURN. 37 | ENDMETHOD. 38 | ENDCLASS. 39 | 40 | START-OF-SELECTION. 41 | PERFORM start. 42 | 43 | FORM start. 44 | TRY. 45 | PERFORM run. 46 | CATCH cx_apc_error INTO DATA(lx_apc_error). 47 | MESSAGE lx_apc_error TYPE 'E'. 48 | ENDTRY. 49 | ENDFORM. 50 | 51 | FORM run RAISING cx_apc_error. 52 | 53 | DATA: li_message_manager TYPE REF TO if_apc_wsp_message_manager, 54 | li_message TYPE REF TO if_apc_wsp_message. 55 | 56 | 57 | DATA(lo_event_handler) = NEW lcl_apc_handler( ). 58 | 59 | DATA(ls_frame) = VALUE apc_tcp_frame( 60 | frame_type = if_apc_tcp_frame_types=>co_frame_type_fixed_length 61 | fixed_length = 1 ). 62 | 63 | DATA(li_client) = cl_apc_tcp_client_manager=>create( 64 | i_host = CONV #( p_host ) 65 | i_port = '80' 66 | i_frame = ls_frame 67 | i_event_handler = lo_event_handler ). 68 | 69 | li_client->connect( ). 70 | 71 | li_message_manager ?= li_client->get_message_manager( ). 72 | li_message ?= li_message_manager->create_message( ). 73 | 74 | DATA(lv_text) = 'GET / HTTP/1.1' && cl_abap_char_utilities=>cr_lf && cl_abap_char_utilities=>cr_lf. 75 | 76 | DATA(lv_hex) = cl_binary_convert=>string_to_xstring_utf8( lv_text ). 77 | 78 | WHILE xstrlen( lv_hex ) > 0. 79 | DATA(lv_single) = lv_hex(1). 80 | li_message->set_binary( lv_single ). 81 | li_message_manager->send( li_message ). 82 | lv_hex = lv_hex+1. 83 | ENDWHILE. 84 | 85 | DATA(lv_str) = ||. 86 | DO 100 TIMES. 87 | CLEAR lo_event_handler->mv_message. 88 | WAIT FOR PUSH CHANNELS UNTIL lo_event_handler->mv_message IS NOT INITIAL UP TO 2 SECONDS. 89 | IF sy-subrc = 8. 90 | WRITE: / 'Timeout occured !'(002). 91 | EXIT. 92 | ELSE. 93 | lv_str = lv_str && lo_event_handler->mv_message. 94 | ENDIF. 95 | ENDDO. 96 | WRITE: / lv_str. 97 | 98 | WRITE: / 'Done'(003). 99 | 100 | ENDFORM. 101 | -------------------------------------------------------------------------------- /src/test/zabapmq_http_client.prog.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPMQ_HTTP_CLIENT 7 | 1 8 | E 9 | X 10 | X 11 | 12 | 13 | 14 | I 15 | 001 16 | Connection closed ! 17 | 29 18 | 19 | 20 | I 21 | 002 22 | Timeout occured ! 23 | 27 24 | 25 | 26 | I 27 | 003 28 | Done 29 | 14 30 | 31 | 32 | R 33 | abapMQ: HTTP client over TCP 34 | 28 35 | 36 | 37 | S 38 | P_HOST 39 | Host 40 | 12 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/test/zabapmq_mqtt.prog.abap: -------------------------------------------------------------------------------- 1 | REPORT zabapmq_mqtt. 2 | 3 | SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME TITLE TEXT-005. 4 | PARAMETERS: 5 | p_rec TYPE c RADIOBUTTON GROUP func DEFAULT 'X', 6 | p_pub TYPE c RADIOBUTTON GROUP func. 7 | SELECTION-SCREEN END OF BLOCK b3. 8 | 9 | SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-002. 10 | PARAMETERS: 11 | p_timeou TYPE i DEFAULT 10 OBLIGATORY, 12 | p_ws TYPE c RADIOBUTTON GROUP tra DEFAULT 'X', 13 | p_url TYPE text100 DEFAULT 'ws://broker.hivemq.com:8000/mqtt' OBLIGATORY, 14 | p_tcp TYPE c RADIOBUTTON GROUP tra, 15 | p_host TYPE text100 DEFAULT 'broker.hivemq.com' OBLIGATORY, 16 | p_port TYPE text100 DEFAULT '1883' OBLIGATORY. 17 | SELECTION-SCREEN END OF BLOCK b2. 18 | 19 | SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. 20 | PARAMETERS: 21 | p_topic TYPE text100 DEFAULT 'ozan/iot2' OBLIGATORY, 22 | p_count TYPE i DEFAULT 3 OBLIGATORY. 23 | SELECTION-SCREEN END OF BLOCK b1. 24 | 25 | SELECTION-SCREEN BEGIN OF BLOCK b4 WITH FRAME TITLE TEXT-006. 26 | PARAMETERS: 27 | p_ptopic TYPE text100 DEFAULT 'ABAP' OBLIGATORY, 28 | p_mess TYPE text100 DEFAULT 'hello world'. 29 | SELECTION-SCREEN END OF BLOCK b4. 30 | 31 | START-OF-SELECTION. 32 | PERFORM run. 33 | 34 | FORM run RAISING cx_apc_error. 35 | 36 | TRY. 37 | CASE abap_true. 38 | WHEN p_ws. 39 | DATA(li_transport) = zcl_mqtt_transport_ws=>create_by_url( CONV #( p_url ) ). 40 | WHEN p_tcp. 41 | li_transport = zcl_mqtt_transport_tcp=>create( 42 | iv_host = CONV #( p_host ) 43 | iv_port = CONV #( p_port ) ). 44 | ENDCASE. 45 | 46 | li_transport->connect( ). 47 | li_transport->send( NEW zcl_mqtt_packet_connect( ) ). 48 | 49 | DATA(lo_connack) = CAST zcl_mqtt_packet_connack( li_transport->listen( p_timeou ) ). 50 | WRITE: / 'CONNACK return code:'(003), lo_connack->get_return_code( ). 51 | 52 | CASE abap_true. 53 | WHEN p_rec. 54 | PERFORM receive USING li_transport. 55 | WHEN p_pub. 56 | PERFORM publish USING li_transport. 57 | WHEN OTHERS. 58 | ASSERT 0 = 1. 59 | ENDCASE. 60 | 61 | li_transport->send( NEW zcl_mqtt_packet_disconnect( ) ). 62 | li_transport->disconnect( ). 63 | 64 | CATCH zcx_mqtt_timeout. 65 | WRITE: / 'timeout'. 66 | CATCH zcx_mqtt. 67 | WRITE: / 'Error'. 68 | ENDTRY. 69 | 70 | ENDFORM. 71 | 72 | FORM receive USING pi_transport TYPE REF TO zif_mqtt_transport RAISING zcx_mqtt cx_apc_error. 73 | 74 | pi_transport->send( NEW zcl_mqtt_packet_subscribe( 75 | it_topics = VALUE #( ( topic = CONV #( p_topic ) ) ) 76 | iv_packet_identifier = '0001' ) ). 77 | DATA(lt_return_codes) = CAST zcl_mqtt_packet_suback( pi_transport->listen( p_timeou ) )->get_return_codes( ). 78 | WRITE: / 'SUBACK return code:'(004), lt_return_codes[ 1 ]. 79 | 80 | WRITE: /. 81 | DO p_count TIMES. 82 | DATA(ls_message) = CAST zcl_mqtt_packet_publish( pi_transport->listen( p_timeou ) )->get_message( ). 83 | WRITE: / ls_message-topic, ls_message-message. 84 | WRITE: / cl_binary_convert=>xstring_utf8_to_string( ls_message-message ). 85 | ENDDO. 86 | 87 | ENDFORM. 88 | 89 | FORM publish USING pi_transport TYPE REF TO zif_mqtt_transport RAISING zcx_mqtt cx_apc_error. 90 | 91 | DATA(ls_message) = VALUE zif_mqtt_packet=>ty_message( 92 | topic = p_ptopic 93 | message = cl_binary_convert=>string_to_xstring_utf8( CONV #( p_mess ) ) ). 94 | 95 | pi_transport->send( NEW zcl_mqtt_packet_publish( is_message = ls_message ) ). 96 | 97 | ENDFORM. 98 | -------------------------------------------------------------------------------- /src/test/zabapmq_mqtt.prog.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPMQ_MQTT 7 | 1 8 | E 9 | X 10 | X 11 | 12 | 13 | 14 | I 15 | 001 16 | Receive messages 17 | 18 18 | 19 | 20 | I 21 | 002 22 | Transport 23 | 19 24 | 25 | 26 | I 27 | 003 28 | CONNACK return code: 29 | 40 30 | 31 | 32 | I 33 | 004 34 | SUBACK return code: 35 | 29 36 | 37 | 38 | I 39 | 005 40 | Function 41 | 18 42 | 43 | 44 | I 45 | 006 46 | Publish message 47 | 25 48 | 49 | 50 | R 51 | abapMQ: MQTT Test Client 52 | 24 53 | 54 | 55 | S 56 | P_COUNT 57 | Count 58 | 13 59 | 60 | 61 | S 62 | P_HOST 63 | Host 64 | 12 65 | 66 | 67 | S 68 | P_MESS 69 | Message 70 | 15 71 | 72 | 73 | S 74 | P_PORT 75 | Port 76 | 12 77 | 78 | 79 | S 80 | P_PTOPIC 81 | Topic 82 | 13 83 | 84 | 85 | S 86 | P_PUB 87 | Publish message 88 | 23 89 | 90 | 91 | S 92 | P_REC 93 | Receive messages 94 | 24 95 | 96 | 97 | S 98 | P_TCP 99 | TCP 100 | 11 101 | 102 | 103 | S 104 | P_TIMEOU 105 | Timeout 106 | 15 107 | 108 | 109 | S 110 | P_TOPIC 111 | Topic 112 | 13 113 | 114 | 115 | S 116 | P_URL 117 | URL 118 | 11 119 | 120 | 121 | S 122 | P_WS 123 | Websocket 124 | 17 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /src/test/zabapmq_performance.prog.abap: -------------------------------------------------------------------------------- 1 | REPORT zabapmq_performance. 2 | 3 | PARAMETERS: p_bytes TYPE i DEFAULT 10000, 4 | p_host TYPE text200 DEFAULT 'google.com', 5 | p_port TYPE text200 DEFAULT '1234'. 6 | 7 | CLASS lcl_apc_handler DEFINITION 8 | FINAL 9 | CREATE PUBLIC. 10 | 11 | PUBLIC SECTION. 12 | INTERFACES: if_apc_wsp_event_handler. 13 | DATA: mv_message TYPE string. 14 | 15 | ENDCLASS. 16 | 17 | CLASS lcl_apc_handler IMPLEMENTATION. 18 | METHOD if_apc_wsp_event_handler~on_open. 19 | RETURN. 20 | ENDMETHOD. 21 | 22 | METHOD if_apc_wsp_event_handler~on_message. 23 | "message handling 24 | TRY. 25 | mv_message = i_message->get_text( ). 26 | CATCH cx_apc_error INTO DATA(lx_apc_error). 27 | mv_message = 'foo' && lx_apc_error->get_text( ). 28 | ENDTRY. 29 | ENDMETHOD. 30 | 31 | METHOD if_apc_wsp_event_handler~on_close. 32 | "close handling 33 | mv_message = 'Connection closed !'(005). 34 | ENDMETHOD. 35 | 36 | METHOD if_apc_wsp_event_handler~on_error. 37 | "error/close handling 38 | RETURN. 39 | ENDMETHOD. 40 | ENDCLASS. 41 | 42 | START-OF-SELECTION. 43 | PERFORM start. 44 | 45 | FORM start. 46 | TRY. 47 | PERFORM run. 48 | CATCH cx_apc_error INTO DATA(lx_apc_error). 49 | MESSAGE lx_apc_error TYPE 'E'. 50 | ENDTRY. 51 | ENDFORM. 52 | 53 | FORM run RAISING cx_apc_error. 54 | 55 | DATA: li_message_manager TYPE REF TO if_apc_wsp_message_manager, 56 | li_message TYPE REF TO if_apc_wsp_message. 57 | 58 | 59 | DATA(lo_event_handler) = NEW lcl_apc_handler( ). 60 | 61 | DATA(ls_frame) = VALUE apc_tcp_frame( 62 | frame_type = if_apc_tcp_frame_types=>co_frame_type_fixed_length 63 | fixed_length = 1 ). 64 | 65 | DATA(li_client) = cl_apc_tcp_client_manager=>create( 66 | i_host = CONV #( p_host ) 67 | i_port = CONV #( p_port ) 68 | i_frame = ls_frame 69 | i_event_handler = lo_event_handler ). 70 | 71 | li_client->connect( ). 72 | 73 | li_message_manager ?= li_client->get_message_manager( ). 74 | li_message ?= li_message_manager->create_message( ). 75 | 76 | GET RUN TIME FIELD DATA(lv_t1). 77 | DO p_bytes TIMES. 78 | li_message->set_binary( '00' ). 79 | li_message_manager->send( li_message ). 80 | ENDDO. 81 | GET RUN TIME FIELD DATA(lv_t2). 82 | 83 | li_client->close( CONV #( 'application closed connection !'(006) ) ). 84 | 85 | lv_t1 = ( lv_t2 - lv_t1 ) / 1000000. 86 | WRITE: / lv_t1. 87 | 88 | WRITE: / 'Done'(007). 89 | 90 | ENDFORM. 91 | -------------------------------------------------------------------------------- /src/test/zabapmq_performance.prog.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPMQ_PERFORMANCE 7 | 1 8 | E 9 | X 10 | X 11 | 12 | 13 | 14 | I 15 | 005 16 | Connection closed ! 17 | 29 18 | 19 | 20 | I 21 | 006 22 | application closed connection ! 23 | 62 24 | 25 | 26 | I 27 | 007 28 | Done 29 | 14 30 | 31 | 32 | R 33 | abapMQ: Test TCP 1 byte performance 34 | 35 35 | 36 | 37 | S 38 | P_BYTES 39 | Bytes 40 | 13 41 | 42 | 43 | S 44 | P_HOST 45 | Host 46 | 12 47 | 48 | 49 | S 50 | P_PORT 51 | Port 52 | 12 53 | 54 | 55 | 56 | 57 | 58 | --------------------------------------------------------------------------------