// //========================================================================= // // Write raw output in Beast Binary format with Timestamp to TCP clients // void modesSendBeastOutput(struct modesMessage *mm) { char *p = &Modes.beastOut[Modes.beastOutUsed]; int msgLen = mm->msgbits / 8; char * pTimeStamp; int j; *p++ = 0x1a; if (msgLen == MODES_SHORT_MSG_BYTES) {*p++ = '2';} else if (msgLen == MODES_LONG_MSG_BYTES) {*p++ = '3';} else if (msgLen == MODEAC_MSG_BYTES) {*p++ = '1';} else {return;} pTimeStamp = (char *) &mm->timestampMsg; for (j = 5; j >= 0; j--) { *p++ = pTimeStamp[j]; } *p++ = mm->signalLevel; memcpy(p, mm->msg, msgLen); Modes.beastOutUsed += (msgLen + 9); if (Modes.beastOutUsed >= Modes.net_output_raw_size) { modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed); Modes.beastOutUsed = 0; Modes.net_output_raw_rate_count = 0; } }
// //========================================================================= // // Write raw output to TCP clients // void modesSendRawOutput(struct modesMessage *mm) { char *p = &Modes.rawOut[Modes.rawOutUsed]; int msgLen = mm->msgbits / 8; int j; unsigned char * pTimeStamp; if (Modes.mlat && mm->timestampMsg) { *p++ = '@'; pTimeStamp = (unsigned char *) &mm->timestampMsg; for (j = 5; j >= 0; j--) { sprintf(p, "%02X", pTimeStamp[j]); p += 2; } Modes.rawOutUsed += 12; // additional 12 characters for timestamp } else *p++ = '*'; for (j = 0; j < msgLen; j++) { sprintf(p, "%02X", mm->msg[j]); p += 2; } *p++ = ';'; *p++ = '\n'; Modes.rawOutUsed += ((msgLen*2) + 3); if (Modes.rawOutUsed >= Modes.net_output_raw_size) { modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed); Modes.rawOutUsed = 0; Modes.net_output_raw_rate_count = 0; } }
// //========================================================================= // // Write raw output in Beast Binary format with Timestamp to TCP clients // void modesSendBeastOutput(struct modesMessage *mm) { char *p = &Modes.beastOut[Modes.beastOutUsed]; int msgLen = mm->msgbits / 8; char * pTimeStamp; char ch; int j; int iOutLen = msgLen + 9; // Escape, msgtype, timestamp, sigLevel, msg *p++ = 0x1a; if (msgLen == MODES_SHORT_MSG_BYTES) {*p++ = '2';} else if (msgLen == MODES_LONG_MSG_BYTES) {*p++ = '3';} else if (msgLen == MODEAC_MSG_BYTES) {*p++ = '1';} else {return;} pTimeStamp = (char *) &mm->timestampMsg; for (j = 5; j >= 0; j--) { *p++ = (ch = pTimeStamp[j]); if (0x1A == ch) {*p++ = ch; iOutLen++;} } *p++ = (ch = mm->signalLevel); if (0x1A == ch) {*p++ = ch; iOutLen++;} for (j = 0; j < msgLen; j++) { *p++ = (ch = mm->msg[j]); if (0x1A == ch) {*p++ = ch; iOutLen++;} } Modes.beastOutUsed += iOutLen; if (Modes.beastOutUsed >= Modes.net_output_raw_size) { modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed); Modes.beastOutUsed = 0; Modes.net_output_raw_rate_count = 0; } }
// //========================================================================= // // Write SBS output to TCP clients // The message structure mm->bFlags tells us what has been updated by this message // void modesSendSBSOutput(struct modesMessage *mm) { char msg[256], *p = msg; uint32_t offset; struct timeb epocTime; struct tm stTime; int msgType; // // SBS BS style output checked against the following reference // http://www.homepages.mcb.net/bones/SBS/Article/Barebones42_Socket_Data.htm - seems comprehensive // // Decide on the basic SBS Message Type if ((mm->msgtype == 4) || (mm->msgtype == 20)) { msgType = 5; } else if ((mm->msgtype == 5) || (mm->msgtype == 21)) { msgType = 6; } else if ((mm->msgtype == 0) || (mm->msgtype == 16)) { msgType = 7; } else if (mm->msgtype == 11) { msgType = 8; } else if ((mm->msgtype != 17) && (mm->msgtype != 18)) { return; } else if ((mm->metype >= 1) && (mm->metype <= 4)) { msgType = 1; } else if ((mm->metype >= 5) && (mm->metype <= 8)) { if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) {msgType = 2;} else {msgType = 7;} } else if ((mm->metype >= 9) && (mm->metype <= 18)) { if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) {msgType = 3;} else {msgType = 7;} } else if (mm->metype != 19) { return; } else if ((mm->mesub == 1) || (mm->mesub == 2)) { msgType = 4; } else { return; } // Fields 1 to 6 : SBS message type and ICAO address of the aircraft and some other stuff p += sprintf(p, "MSG,%d,111,11111,%06X,111111,", msgType, mm->addr); // Fields 7 & 8 are the current time and date if (mm->timestampMsg) { // Make sure the records' timestamp is valid before outputing it epocTime = Modes.stSystemTimeBlk; // This is the time of the start of the Block we're processing offset = (int) (mm->timestampMsg - Modes.timestampBlk); // This is the time (in 12Mhz ticks) into the Block offset = offset / 12000; // convert to milliseconds epocTime.millitm += offset; // add on the offset time to the Block start time if (epocTime.millitm > 999) // if we've caused an overflow into the next second... {epocTime.millitm -= 1000; epocTime.time ++;} // ..correct the overflow stTime = *localtime(&epocTime.time); // convert the time to year, month day, hours, min, sec p += sprintf(p, "%04d/%02d/%02d,", (stTime.tm_year+1900),(stTime.tm_mon+1), stTime.tm_mday); p += sprintf(p, "%02d:%02d:%02d.%03d,", stTime.tm_hour, stTime.tm_min, stTime.tm_sec, epocTime.millitm); } else { p += sprintf(p, ",,"); } // Fields 9 & 10 are the current time and date ftime(&epocTime); // get the current system time & date stTime = *localtime(&epocTime.time); // convert the time to year, month day, hours, min, sec p += sprintf(p, "%04d/%02d/%02d,", (stTime.tm_year+1900),(stTime.tm_mon+1), stTime.tm_mday); p += sprintf(p, "%02d:%02d:%02d.%03d", stTime.tm_hour, stTime.tm_min, stTime.tm_sec, epocTime.millitm); // Field 11 is the callsign (if we have it) if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {p += sprintf(p, ",%s", mm->flight);} else {p += sprintf(p, ",");} // Field 12 is the altitude (if we have it) - force to zero if we're on the ground if ((mm->bFlags & MODES_ACFLAGS_AOG_GROUND) == MODES_ACFLAGS_AOG_GROUND) { p += sprintf(p, ",0"); } else if (mm->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) { p += sprintf(p, ",%d", mm->altitude); } else { p += sprintf(p, ","); } // Field 13 and 14 are the ground Speed and Heading (if we have them) if (mm->bFlags & MODES_ACFLAGS_NSEWSPD_VALID) {p += sprintf(p, ",%d,%d", mm->velocity, mm->heading);} else {p += sprintf(p, ",,");} // Fields 15 and 16 are the Lat/Lon (if we have it) if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) {p += sprintf(p, ",%1.5f,%1.5f", mm->fLat, mm->fLon);} else {p += sprintf(p, ",,");} // Field 17 is the VerticalRate (if we have it) if (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) {p += sprintf(p, ",%d", mm->vert_rate);} else {p += sprintf(p, ",");} // Field 18 is the Squawk (if we have it) if (mm->bFlags & MODES_ACFLAGS_SQUAWK_VALID) {p += sprintf(p, ",%x", mm->modeA);} else {p += sprintf(p, ",");} // Field 19 is the Squawk Changing Alert flag (if we have it) if (mm->bFlags & MODES_ACFLAGS_FS_VALID) { if ((mm->fs >= 2) && (mm->fs <= 4)) { p += sprintf(p, ",-1"); } else { p += sprintf(p, ",0"); } } else { p += sprintf(p, ","); } // Field 20 is the Squawk Emergency flag (if we have it) if (mm->bFlags & MODES_ACFLAGS_SQUAWK_VALID) { if ((mm->modeA == 0x7500) || (mm->modeA == 0x7600) || (mm->modeA == 0x7700)) { p += sprintf(p, ",-1"); } else { p += sprintf(p, ",0"); } } else { p += sprintf(p, ","); } // Field 21 is the Squawk Ident flag (if we have it) if (mm->bFlags & MODES_ACFLAGS_FS_VALID) { if ((mm->fs >= 4) && (mm->fs <= 5)) { p += sprintf(p, ",-1"); } else { p += sprintf(p, ",0"); } } else { p += sprintf(p, ","); } // Field 22 is the OnTheGround flag (if we have it) if (mm->bFlags & MODES_ACFLAGS_AOG_VALID) { if (mm->bFlags & MODES_ACFLAGS_AOG) { p += sprintf(p, ",-1"); } else { p += sprintf(p, ",0"); } } else { p += sprintf(p, ","); } p += sprintf(p, "\r\n"); modesSendAllClients(Modes.sbsos, msg, p-msg); }