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