JS8Call-Improved master
Loading...
Searching...
No Matches
NetworkMessage.h
1#ifndef NETWORK_MESSAGE_HPP__
2#define NETWORK_MESSAGE_HPP__
3
4/*
5 * WSJT-X Message Formats
6 * ======================
7 *
8 * All messages are written or read using the QDataStream derivatives
9 * defined below, note that we are using the default for floating
10 * point precision which means all are double precision i.e. 64-bit
11 * IEEE format.
12 *
13 * Message is big endian format
14 *
15 * Header format:
16 *
17 * 32-bit unsigned integer magic number 0xadbccbda
18 * 32-bit unsigned integer schema number
19 *
20 * Payload format:
21 *
22 * As per the QDataStream format, see below for version used and
23 * here:
24 *
25 * http://doc.qt.io/qt-5/datastreamformat.html
26 *
27 * for the serialization details for each type, at the time of
28 * writing the above document is for Qt_5_0 format which is buggy
29 * so we use Qt_5_4 format, differences are:
30 *
31 * QDateTime:
32 * QDate qint64 Julian day number
33 * QTime quint32 Milli-seconds since midnight
34 * timespec quint8 0=local, 1=UTC, 2=Offset from UTC
35 * (seconds)
36 * 3=time zone
37 * offset qint32 only present if timespec=2
38 * timezone several-fields only present if timespec=3
39 *
40 * we will avoid using QDateTime fields with time zones for
41 * simplicity.
42 *
43 * Type utf8 is a utf-8 byte string formatted as a QByteArray for
44 * serialization purposes (currently a quint32 size followed by size
45 * bytes, no terminator is present or counted).
46 *
47 * The QDataStream format document linked above is not complete for
48 * the QByteArray serialization format, it is similar to the QString
49 * serialization format in that it differentiates between empty
50 * strings and null strings. Empty strings have a length of zero
51 * whereas null strings have a length field of 0xffffffff.
52 *
53 *
54 * Schema Negotiation
55 * ------------------
56 *
57 * The NetworkMessage::Builder class specifies a schema number which
58 * may be incremented from time to time. It represents a version of
59 * the underlying encoding schemes used to store data items. Since the
60 * underlying encoding is defined by the Qt project in it's
61 * QDataStream stream operators, it is essential that clients and
62 * servers of this protocol can agree on a common scheme. The
63 * NetworkMessage utility classes below exchange the schema number
64 * actually used. The handling of the schema is backwards compatible
65 * to an extent, so long as clients and servers are written
66 * correctly. For example a server written to any particular schema
67 * version can communicate with a client written to a later schema.
68 *
69 * Schema Version 1:- this schema used the QDataStream::Qt_5_0 version
70 * which is broken.
71 *
72 * Schema Version 2:- this schema uses the QDataStream::Qt_5_2 version.
73 *
74 * Schema Version 3:- this schema uses the QDataStream::Qt_5_4 version.
75 *
76 *
77 * Backward Compatibility
78 * ----------------------
79 *
80 * It is important that applications developed at different times
81 * remain compatible with this protocol and with older or newer
82 * versions of WSJT-X. This is achieved by both third-party
83 * applications and WSJT-X honouring two basic rules.
84 *
85 * 1. New message types may be added to the protocol in the future,
86 * third-party applications and WSJT-X shall ignore silently any
87 * message types they do not recognize.
88 *
89 * 2. New fields may be added to existing message types, they will
90 * always be added to the end of the existing fields and the number
91 * and type of existing fields shall not change. If a field type
92 * must be changed; a new field will be added and the existing
93 * field will remain. The originator of such a message shall
94 * populate both the new and old field with reasonable
95 * values. Third-party applications and WSJT-X shall ignore
96 * silently any extra data received in datagrams after the fields
97 * they know about.
98 *
99 * Note that these rules are unrelated to the schema number above
100 * whose purpose is to distinguish between non-compatible encodings of
101 * field data types. New message types and extra fields in existing
102 * messages can and will be added without any change in schema number.
103 *
104 *
105 * Message Types
106 * -------------
107 *
108 * Message Direction Value Type
109 * ------------- --------- ---------------------- -----------
110 * Heartbeat Out/In 0 quint32
111 * Id (unique key) utf8
112 * Maximum schema number quint32
113 * version utf8
114 * revision utf8
115 *
116 * The heartbeat message shall be sent on a periodic basis every
117 * NetworkMessage::pulse seconds (see below), the WSJT-X
118 * application does that using the MessageClient class. This
119 * message is intended to be used by servers to detect the presence
120 * of a client and also the unexpected disappearance of a client
121 * and by clients to learn the schema negotiated by the server
122 * after it receives the initial heartbeat message from a client.
123 * The message_aggregator reference server does just that using the
124 * MessageServer class. Upon initial startup a client must send a
125 * heartbeat message as soon as is practical, this message is used
126 * to negotiate the maximum schema number common to the client and
127 * server. Note that the server may not be able to support the
128 * client's requested maximum schema number, in which case the
129 * first message received from the server will specify a lower
130 * schema number (never a higher one as that is not allowed). If a
131 * server replies with a lower schema number then no higher than
132 * that number shall be used for all further outgoing messages from
133 * either clients or the server itself.
134 *
135 * Note: the "Maximum schema number" field was introduced at the
136 * same time as schema 3, therefore servers and clients must assume
137 * schema 2 is the highest schema number supported if the Heartbeat
138 * message does not contain the "Maximum schema number" field.
139 *
140 *
141 * Status Out 1 quint32
142 * Id (unique key) utf8
143 * Dial Frequency (Hz) quint64
144 * Mode utf8
145 * DX call utf8
146 * Report utf8
147 * Tx Mode utf8
148 * Tx Enabled bool
149 * Transmitting bool
150 * Decoding bool
151 * Rx DF quint32
152 * Tx DF quint32
153 * DE call utf8
154 * DE grid utf8
155 * DX grid utf8
156 * Tx Watchdog bool
157 * Sub-mode utf8
158 * Fast mode bool
159 * Special Operation Mode quint8
160 * Frequency Tolerance quint32
161 * T/R Period quint32
162 * Configuration Name utf8
163 * Tx Message utf8
164 *
165 * WSJT-X sends this status message when various internal state
166 * changes to allow the server to track the relevant state of each
167 * client without the need for polling commands. The current state
168 * changes that generate status messages are:
169 *
170 * Application start up,
171 * "Enable Tx" button status changes,
172 * dial frequency changes,
173 * changes to the "DX Call" field,
174 * operating mode, sub-mode or fast mode changes,
175 * transmit mode changed (in dual JT9+JT65 mode),
176 * changes to the "Rpt" spinner,
177 * after an old decodes replay sequence (see Replay below),
178 * when switching between Tx and Rx mode,
179 * at the start and end of decoding,
180 * when the Rx DF changes,
181 * when the Tx DF changes,
182 * when settings are exited,
183 * when the DX call or grid changes,
184 * when the Tx watchdog is set or reset,
185 * when the frequency tolerance is changed,
186 * when the T/R period is changed,
187 * when the configuration name changes,
188 * when the message being transmitted changes.
189 *
190 * The Special operation mode is an enumeration that indicates the
191 * setting selected in the WSJT-X "Settings->Advanced->Special
192 * operating activity" panel. The values are as follows:
193 *
194 * 0 -> NONE
195 * 1 -> NA VHF
196 * 2 -> EU VHF
197 * 3 -> FIELD DAY
198 * 4 -> RTTY RU
199 * 5 -> WW DIGI
200 * 6 -> FOX
201 * 7 -> HOUND
202 * 8 -> ARRL DIGI
203 *
204 * The Frequency Tolerance and T/R period fields may have a value
205 * of the maximum quint32 value which implies the field is not
206 * applicable.
207 *
208 *
209 * Decode Out 2 quint32
210 * Id (unique key) utf8
211 * New bool
212 * Time QTime
213 * snr qint32
214 * Delta time (S) float (serialized as double)
215 * Delta frequency (Hz) quint32
216 * Mode utf8
217 * Message utf8
218 * Low confidence bool
219 * Off air bool
220 *
221 * The decode message is sent when a new decode is completed, in
222 * this case the 'New' field is true. It is also used in response
223 * to a "Replay" message where each old decode in the "Band
224 * activity" window, that has not been erased, is sent in order
225 * as a one of these messages with the 'New' field set to false.
226 * See the "Replay" message below for details of usage. Low
227 * confidence decodes are flagged in protocols where the decoder
228 * has knows that a decode has a higher than normal probability
229 * of being false, they should not be reported on publicly
230 * accessible services without some attached warning or further
231 * validation. Off air decodes are those that result from playing
232 * back a .WAV file.
233 *
234 *
235 * Clear Out/In 3 quint32
236 * Id (unique key) utf8
237 * Window quint8 (In only)
238 *
239 * This message is send when all prior "Decode" messages in the
240 * "Band Activity" window have been discarded and therefore are
241 * no long available for actioning with a "Reply" message. It is
242 * sent when the user erases the "Band activity" window and when
243 * WSJT-X closes down normally. The server should discard all
244 * decode messages upon receipt of this message.
245 *
246 * It may also be sent to a WSJT-X instance in which case it
247 * clears one or both of the "Band Activity" and "Rx Frequency"
248 * windows. The Window argument can be one of the following
249 * values:
250 *
251 * 0 - clear the "Band Activity" window (default)
252 * 1 - clear the "Rx Frequency" window
253 * 2 - clear both "Band Activity" and "Rx Frequency" windows
254 *
255 *
256 * Reply In 4 quint32
257 * Id (target unique key) utf8
258 * Time QTime
259 * snr qint32
260 * Delta time (S) float (serialized as double)
261 * Delta frequency (Hz) quint32
262 * Mode utf8
263 * Message utf8
264 * Low confidence bool
265 * Modifiers quint8
266 *
267 * In order for a server to provide a useful cooperative service
268 * to WSJT-X it is possible for it to initiate a QSO by sending
269 * this message to a client. WSJT-X filters this message and only
270 * acts upon it if the message exactly describes a prior decode
271 * and that decode is a CQ or QRZ message. The action taken is
272 * exactly equivalent to the user double clicking the message in
273 * the "Band activity" window. The intent of this message is for
274 * servers to be able to provide an advanced look up of potential
275 * QSO partners, for example determining if they have been worked
276 * before or if working them may advance some objective like
277 * award progress. The intention is not to provide a secondary
278 * user interface for WSJT-X, it is expected that after QSO
279 * initiation the rest of the QSO is carried out manually using
280 * the normal WSJT-X user interface.
281 *
282 * The Modifiers field allows the equivalent of keyboard
283 * modifiers to be sent "as if" those modifier keys where pressed
284 * while double-clicking the specified decoded message. The
285 * modifier values (hexadecimal) are as follows:
286 *
287 * no modifier 0x00
288 * SHIFT 0x02
289 * CTRL 0x04 CMD on Mac
290 * ALT 0x08
291 * META 0x10 Windows key on MS Windows
292 * KEYPAD 0x20 Keypad or arrows
293 * Group switch 0x40 X11 only
294 *
295 *
296 * QSO Logged Out 5 quint32
297 * Id (unique key) utf8
298 * Date & Time Off QDateTime
299 * DX call utf8
300 * DX grid utf8
301 * Tx frequency (Hz) quint64
302 * Mode utf8
303 * Report sent utf8
304 * Report received utf8
305 * Tx power utf8
306 * Comments utf8
307 * Name utf8
308 * Date & Time On QDateTime
309 * Operator call utf8
310 * My call utf8
311 * My grid utf8
312 * Exchange sent utf8
313 * Exchange received utf8
314 * ADIF Propagation mode utf8
315 *
316 * The QSO logged message is sent to the server(s) when the
317 * WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"
318 * button.
319 *
320 *
321 * Close Out/In 6 quint32
322 * Id (unique key) utf8
323 *
324 * Close is sent by a client immediately prior to it shutting
325 * down gracefully. When sent by a server it requests the target
326 * client to close down gracefully.
327 *
328 *
329 * Replay In 7 quint32
330 * Id (unique key) utf8
331 *
332 * When a server starts it may be useful for it to determine the
333 * state of preexisting clients. Sending this message to each
334 * client as it is discovered will cause that client (WSJT-X) to
335 * send a "Decode" message for each decode currently in its "Band
336 * activity" window. Each "Decode" message sent will have the
337 * "New" flag set to false so that they can be distinguished from
338 * new decodes. After all the old decodes have been broadcast a
339 * "Status" message is also broadcast. If the server wishes to
340 * determine the status of a newly discovered client; this
341 * message should be used.
342 *
343 *
344 * Halt Tx In 8
345 * Id (unique key) utf8
346 * Auto Tx Only bool
347 *
348 * The server may stop a client from transmitting messages either
349 * immediately or at the end of the current transmission period
350 * using this message.
351 *
352 *
353 * Free Text In 9
354 * Id (unique key) utf8
355 * Text utf8
356 * Send bool
357 *
358 * This message allows the server to set the current free text
359 * message content. Sending this message with a non-empty "Text"
360 * field is equivalent to typing a new message (old contents are
361 * discarded) in to the WSJT-X free text message field or "Tx5"
362 * field (both are updated) and if the "Send" flag is set then
363 * clicking the "Now" radio button for the "Tx5" field if tab one
364 * is current or clicking the "Free msg" radio button if tab two
365 * is current.
366 *
367 * It is the responsibility of the sender to limit the length of
368 * the message text and to limit it to legal message
369 * characters. Despite this, it may be difficult for the sender
370 * to determine the maximum message length without reimplementing
371 * the complete message encoding protocol. Because of this is may
372 * be better to allow any reasonable message length and to let
373 * the WSJT-X application encode and possibly truncate the actual
374 * on-air message.
375 *
376 * If the message text is empty the meaning of the message is
377 * refined to send the current free text unchanged when the
378 * "Send" flag is set or to clear the current free text when the
379 * "Send" flag is unset. Note that this API does not include a
380 * command to determine the contents of the current free text
381 * message.
382 *
383 *
384 * WSPRDecode Out 10 quint32
385 * Id (unique key) utf8
386 * New bool
387 * Time QTime
388 * snr qint32
389 * Delta time (S) float (serialized as double)
390 * Frequency (Hz) quint64
391 * Drift (Hz) qint32
392 * Callsign utf8
393 * Grid utf8
394 * Power (dBm) qint32
395 * Off air bool
396 *
397 * The decode message is sent when a new decode is completed, in
398 * this case the 'New' field is true. It is also used in response
399 * to a "Replay" message where each old decode in the "Band
400 * activity" window, that has not been erased, is sent in order
401 * as a one of these messages with the 'New' field set to
402 * false. See the "Replay" message below for details of
403 * usage. The off air field indicates that the decode was decoded
404 * from a played back recording.
405 *
406 *
407 * Location In 11
408 * Id (unique key) utf8
409 * Location utf8
410 *
411 * This message allows the server to set the current current
412 * geographical location of operation. The supplied location is
413 * not persistent but is used as a session lifetime replacement
414 * loction that overrides the Maidenhead grid locater set in the
415 * application settings. The intent is to allow an external
416 * application to update the operating location dynamically
417 * during a mobile period of operation.
418 *
419 * Currently only Maidenhead grid squares or sub-squares are
420 * accepted, i.e. 4- or 6-digit locators. Other formats may be
421 * accepted in future.
422 *
423 *
424 * Logged ADIF Out 12 quint32
425 * Id (unique key) utf8
426 * ADIF text utf8
427 *
428 * The logged ADIF message is sent to the server(s) when the
429 * WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"
430 * button. The "ADIF text" field consists of a valid ADIF file
431 * such that the WSJT-X UDP header information is encapsulated
432 * into a valid ADIF header. E.g.:
433 *
434 * <magic-number><schema-number><type><id><32-bit-count> # binary
435 * encoded fields # the remainder is the contents of the ADIF text field
436 * <adif_ver:5>3.0.7
437 * <programid:6>WSJT-X
438 * <EOH>
439 * ADIF log data fields ...<EOR>
440 *
441 * Note that receiving applications can treat the whole message
442 * as a valid ADIF file with one record without special parsing.
443 *
444 *
445 * Highlight Callsign In 13 quint32
446 * Id (unique key) utf8
447 * Callsign utf8
448 * Background Color QColor
449 * Foreground Color QColor
450 * Highlight last bool
451 *
452 * The server may send this message at any time. The message
453 * specifies the background and foreground color that will be
454 * used to highlight the specified callsign in the decoded
455 * messages printed in the Band Activity panel. The WSJT-X
456 * clients maintain a list of such instructions and apply them to
457 * all decoded messages in the band activity window. To clear
458 * and cancel highlighting send an invalid QColor value for
459 * either or both of the background and foreground fields. When
460 * using this mode the total number of callsign highlighting
461 * requests should be limited otherwise the performance of WSJT-X
462 * decoding may be impacted. A rough rule of thumb might be too
463 * limit the number of active highlighting requests to no more
464 * than 100.
465 *
466 * Using a callsign of "CLEARALL!" and anything for the
467 * color values will clear the internal highlighting data. It will
468 * NOT remove the highlighting on the screen, however. The exclamation
469 * symbol is used to avoid accidental clearing of all highlighting
470 * data via a decoded callsign, since an exclamation symbol is not
471 * a valid character in a callsign.
472 *
473 * The "Highlight last" field allows the sender to request that
474 * all instances of "Callsign" in the last period only, instead
475 * of all instances in all periods, be highlighted.
476 *
477 *
478 * SwitchConfiguration In 14 quint32
479 * Id (unique key) utf8
480 * Configuration Name utf8
481 *
482 * The server may send this message at any time. The message
483 * specifies the name of the configuration to switch to. The new
484 * configuration must exist.
485 *
486 *
487 * Configure In 15 quint32
488 * Id (unique key) utf8
489 * Mode utf8
490 * Frequency Tolerance quint32
491 * Submode utf8
492 * Fast Mode bool
493 * T/R Period quint32
494 * Rx DF quint32
495 * DX Call utf8
496 * DX Grid utf8
497 * Generate Messages bool
498 *
499 * The server may send this message at any time. The message
500 * specifies various configuration options. For utf8 string
501 * fields an empty value implies no change, for the quint32 Rx DF
502 * and Frequency Tolerance fields the maximum quint32 value
503 * implies no change. Invalid or unrecognized values will be
504 * silently ignored. NOTE that if a mode/submode change occurs and
505 * the current frequency is NOT in the frequency table for that
506 * mode, a frequency change (to the default frequency for that band
507 * and mode) may occur.
508 *
509 * AnnotationInfo In 16 quint32
510 * Id (unique key) utf8
511 * DX Call utf8
512 * Sort Order Provided bool
513 * Sort Order quint32
514 *
515 * The server may send this message at any time. Sort orders can be used
516 * for sorting hound callers when in Fox mode. A typical usage is to
517 * "score" callsigns based on number of bands and/or modes worked using
518 * an external logging program during a DXpedition, to be able to give
519 * preference to calls that have not been worked before on any other
520 * band or mode. An external program can watch decodes from wsjt-x,
521 * then use this message to annotate the calls with a sort order. The
522 * hound queue can be displayed by that sort order. *
523 *
524 * If 'sort order provided' is true, the message also specifies a numeric
525 * sort order for the DX call.
526 *
527 * Invalid or unrecognized values will be silently ignored. A sort-order
528 * of ffffffff will remove the sort-order value from the internal table.
529 * Callsigns without a sort order will be valued at zero for sorting
530 * purposes in the hound display.
531 */
532
533#include "JS8_Include/pimpl_h.h"
534
535#include <QDataStream>
536
537class QIODevice;
538class QByteArray;
539class QString;
540
541namespace NetworkMessage {
542// NEVER DELETE MESSAGE TYPES
543enum Type {
544 Heartbeat,
545 Status,
546 Decode,
547 Clear,
548 Reply,
549 QSOLogged,
550 Close,
551 Replay,
552 HaltTx,
553 FreeText,
554 WSPRDecode,
555 Location,
556 LoggedADIF,
557 HighlightCallsign,
558 SwitchConfiguration,
559 Configure,
560 AnnotationInfo,
561 maximum_message_type_ // ONLY add new message types
562 // immediately before here
563};
564
565quint32 constexpr pulse{15}; // seconds
566
567//
568// NetworkMessage::Builder - build a message containing serialized Qt types
569//
570class Builder : public QDataStream {
571 public:
572 static quint32 constexpr magic{0xadbccbda}; // never change this
573
574 // increment this if a newer Qt schema is required and add decode
575 // logic to the Builder and Reader class implementations
576#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
577 static quint32 constexpr schema_number{3};
578#elif QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
579 static quint32 constexpr schema_number{2};
580#else
581 // Schema 1 (Qt_5_0) is broken
582#error "Qt version 5.2 or greater required"
583#endif
584
585 explicit Builder(QIODevice *, Type, QString const &id, quint32 schema);
586 explicit Builder(QByteArray *, Type, QString const &id, quint32 schema);
587 Builder(Builder const &) = delete;
588 Builder &operator=(Builder const &) = delete;
589
590 private:
591 void common_initialization(Type type, QString const &id, quint32 schema);
592};
593
594//
595// NetworkMessage::Reader - read a message containing serialized Qt types
596//
597// Message is as per NetworkMessage::Builder above, the schema()
598// member may be used to determine the schema of the original
599// message.
600//
601class Reader : public QDataStream {
602 public:
603 explicit Reader(QIODevice *);
604 explicit Reader(QByteArray const &);
605 Reader(Reader const &) = delete;
606 Reader &operator=(Reader const &) = delete;
607 ~Reader();
608
609 quint32 schema() const;
610 Type type() const;
611 QString id() const;
612
613 private:
614 class impl;
615 pimpl<impl> m_;
616};
617} // namespace NetworkMessage
618
619#endif
Definition NetworkMessage.cpp:56
Definition pimpl_h.h:16