|
| 1 | + |
| 2 | +stack-clear |
| 3 | +\ common words for communication with mqtt broker |
| 4 | +NETCON load |
| 5 | +DECOMP load |
| 6 | + |
| 7 | +\ configuration for communicating with your broker |
| 8 | +"192.168.1.172" constant: broker_addr |
| 9 | +1883 constant: broker_port |
| 10 | +"YourMQTT-ClientId" constant: mqtt-clientid |
| 11 | + |
| 12 | +\ mqtt message types |
| 13 | +\ 10 = CONNECT message type |
| 14 | +16r10 constant: msgtype_connect |
| 15 | +16r20 constant: msgtype_conact |
| 16 | +16rE0 constant: msgtype_disconnect |
| 17 | +16r30 constant: msgtype_publish |
| 18 | +16r82 constant: msgtype_subscribe |
| 19 | +16r90 constant: msgtype_subresp |
| 20 | + |
| 21 | +\ socket reference to broker |
| 22 | +variable: broker |
| 23 | + |
| 24 | +\ communication packet buffer. expect small packets |
| 25 | +255 constant: packet_size |
| 26 | +packet_size byte-array: packet |
| 27 | +\ paki is an index into packet byte array when building the packet |
| 28 | +\ note that the packet size to send is 1+ the paki value |
| 29 | +variable: paki |
| 30 | + |
| 31 | +\ store two byte number into an address |
| 32 | +: !pack-num ( num addr -- ) |
| 33 | + 2dup |
| 34 | + \ store high order byte to address |
| 35 | + swap 8 rshift swap c! |
| 36 | + \ store low order byte to address+1 |
| 37 | + 1+ c! ; |
| 38 | + |
| 39 | +\ store string at an address |
| 40 | +: !str ( s addr -- ) |
| 41 | + swap dup strlen ( addr s len ) |
| 42 | + rot swap ( s addr len ) |
| 43 | + cmove ; |
| 44 | + |
| 45 | +\ store string into len+string struct that mqtt likes (packed string) |
| 46 | +: !pack-str ( s addr -- len) |
| 47 | + 2dup ( s addr s addr) |
| 48 | + swap strlen dup >r swap ( s addr len addr) |
| 49 | + !pack-num ( s addr) |
| 50 | + \ fill rest of buffer with the string |
| 51 | + 2 + ( s addr ) |
| 52 | + r> dup >r ( s addr len ) |
| 53 | + cmove ( ) |
| 54 | + \ return length of string we just stored plus the length of num |
| 55 | + r> 2 + |
| 56 | + ; |
| 57 | + |
| 58 | +\ establish tcp socket connection to broker |
| 59 | +: mqtt-con broker_port broker_addr TCP netcon-connect broker ! ; |
| 60 | +: mqtt-close broker @ netcon-dispose ; |
| 61 | +\ send packet to broker |
| 62 | +: send-pak broker @ rot rot netcon-write-buf ; |
| 63 | +: send-packet 0 packet paki @ send-pak ; |
| 64 | +\ store single byte character in packet |
| 65 | +: !c-packet ( c -- ) paki @ packet c! 1 paki +! ; |
| 66 | +\ store packed string in packet |
| 67 | +: !str-packet ( s -- ) paki @ packet !pack-str paki +! ; |
| 68 | +\ store message length in the packet header ie. packet size - 2 |
| 69 | +: !packet-len paki @ 2 - 1 packet c! ; |
| 70 | + |
| 71 | +\ stores mqtt CONNECT command into packet |
| 72 | +: make-packet-connect |
| 73 | + \ initialize the index into the byte-array |
| 74 | + 0 paki ! |
| 75 | + msgtype_connect !c-packet |
| 76 | + 1 paki +! |
| 77 | + \ msg len, must be calculated at the end |
| 78 | + \ protocol name |
| 79 | + "MQTT" !str-packet |
| 80 | + \ protocol version |
| 81 | + 16r04 !c-packet |
| 82 | + \ flags |
| 83 | + 16r02 !c-packet |
| 84 | + \ keep-alive |
| 85 | + 60 paki @ packet !pack-num |
| 86 | + 2 paki +! |
| 87 | + \ clientid |
| 88 | + mqtt-clientid !str-packet |
| 89 | + !packet-len |
| 90 | + ; |
| 91 | + |
| 92 | +: make-packet-disconnect ( -- ) |
| 93 | + 0 paki ! |
| 94 | + msgtype_disconnect !c-packet |
| 95 | + 1 paki +! |
| 96 | + \ 2 - 2 = 0, will store 0 |
| 97 | + !packet-len ; |
| 98 | + |
| 99 | +: make-packet-publish ( topic msg -- ) |
| 100 | + 0 paki ! |
| 101 | + msgtype_publish !c-packet |
| 102 | + 1 paki +! |
| 103 | + \ store topic with length |
| 104 | + swap !str-packet |
| 105 | + dup strlen swap paki @ packet !str paki +! |
| 106 | + !packet-len ; |
| 107 | + |
| 108 | +\ compare buffer contents |
| 109 | +: =buf ( b1 b2 n -- T|F) |
| 110 | + 0 do |
| 111 | + 2dup |
| 112 | + i + c@ swap i + c@ <> if |
| 113 | + 2drop unloop FALSE exit then |
| 114 | + loop |
| 115 | + 2drop TRUE ; |
| 116 | + |
| 117 | +\ read message from broker into packet and store length |
| 118 | +: read-broker broker @ packet_size 0 packet netcon-read |
| 119 | + paki ! ; |
| 120 | + |
| 121 | +\ compare broker response to expected response |
| 122 | +: expect ( buf n -- TRUE | FALSE) |
| 123 | + paki @ |
| 124 | + dup -1 = if \ no bytes read from broker |
| 125 | + 2drop FALSE exit |
| 126 | + then |
| 127 | + dup rot <> if \ did not read the expected number of bytes |
| 128 | + 2drop FALSE exit |
| 129 | + then |
| 130 | + 0 packet swap =buf ; |
| 131 | + |
| 132 | +create: pak-conack 16r20 c, 16r02 c, 16r00 c, 16r00 c, |
| 133 | +create: pak-disconnect 16re0 c, 16r00 c, |
| 134 | + |
| 135 | +: expect-conack pak-conack 4 expect ; |
| 136 | + |
| 137 | +: print-results |
| 138 | + if |
| 139 | + println: "Success" else println: "Failed" |
| 140 | + print: "got " paki @ . print: " bytes" cr |
| 141 | + then |
| 142 | + 0 packet 10 dump ; |
| 143 | + |
| 144 | +: mqtt-pub |
| 145 | + make-packet-connect mqtt-con send-packet |
| 146 | + read-broker expect-conack if |
| 147 | + make-packet-publish send-packet |
| 148 | + pak-disconnect 2 send-pak |
| 149 | + then mqtt-close ; |
| 150 | + |
| 151 | +\ example usage |
| 152 | +\ "house/t1" "testmessage" mqtt-pub |
| 153 | +\ print-results |
| 154 | +/end |
| 155 | + |
0 commit comments