kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
commit
ba86f90dd2
|
@ -897,6 +897,7 @@ def main():
|
|||
),
|
||||
launch_notifications=config["email_launch_notifications"],
|
||||
landing_notifications=config["email_landing_notifications"],
|
||||
encrypted_sonde_notifications=config["email_encrypted_sonde_notifications"],
|
||||
landing_range_threshold=config["email_landing_range_threshold"],
|
||||
landing_altitude_threshold=config["email_landing_altitude_threshold"],
|
||||
)
|
||||
|
|
|
@ -12,7 +12,7 @@ from queue import Queue
|
|||
# MINOR - New sonde type support, other fairly big changes that may result in telemetry or config file incompatability issus.
|
||||
# PATCH - Small changes, or minor feature additions.
|
||||
|
||||
__version__ = "1.6.1"
|
||||
__version__ = "1.6.2-beta1"
|
||||
|
||||
|
||||
# Global Variables
|
||||
|
|
|
@ -748,6 +748,17 @@ def read_auto_rx_config(filename, no_sdr_test=False):
|
|||
"Config - Did not find system / debug logging options, using defaults (disabled, unless set as a command-line option.)"
|
||||
)
|
||||
|
||||
# 1.6.2 - Encrypted Sonde Email Notifications
|
||||
try:
|
||||
auto_rx_config["email_encrypted_sonde_notifications"] = config.getboolean(
|
||||
"email", "encrypted_sonde_notifications"
|
||||
)
|
||||
except:
|
||||
logging.warning(
|
||||
"Config - Did not find encrypted_sonde_notifications setting (new in v1.6.2), using default (True)"
|
||||
)
|
||||
auto_rx_config["email_encrypted_sonde_notifications"] = True
|
||||
|
||||
|
||||
# If we are being called as part of a unit test, just return the config now.
|
||||
if no_sdr_test:
|
||||
|
|
|
@ -23,6 +23,7 @@ from .gps import get_ephemeris, get_almanac
|
|||
from .sonde_specific import fix_datetime, imet_unique_id
|
||||
from .fsk_demod import FSKDemodStats
|
||||
from .sdr_wrappers import test_sdr, get_sdr_iq_cmd, get_sdr_fm_cmd, get_sdr_name
|
||||
from .email_notification import EmailNotification
|
||||
|
||||
# Global valid sonde types list.
|
||||
VALID_SONDE_TYPES = [
|
||||
|
@ -1424,6 +1425,20 @@ class SondeDecoder(object):
|
|||
"Radiosonde %s has encrypted telemetry (Possible encrypted RS41-SGM)! We cannot decode this, closing decoder."
|
||||
% _telemetry["id"]
|
||||
)
|
||||
|
||||
# Overwrite the datetime field to make the email notifier happy
|
||||
_telemetry['datetime_dt'] = datetime.datetime.utcnow()
|
||||
_telemetry["freq"] = "%.3f MHz" % (self.sonde_freq / 1e6)
|
||||
|
||||
# Send this to only the Email Notifier, if it exists.
|
||||
for _exporter in self.exporters:
|
||||
try:
|
||||
if _exporter.__self__.__module__ == EmailNotification.__module__:
|
||||
_exporter(_telemetry)
|
||||
except Exception as e:
|
||||
self.log_error("Exporter Error %s" % str(e))
|
||||
|
||||
# Close the decoder.
|
||||
self.exit_state = "Encrypted"
|
||||
self.decoder_running = False
|
||||
return False
|
||||
|
|
|
@ -43,6 +43,7 @@ class EmailNotification(object):
|
|||
station_position=None,
|
||||
launch_notifications=True,
|
||||
landing_notifications=True,
|
||||
encrypted_sonde_notifications=True,
|
||||
landing_range_threshold=50,
|
||||
landing_altitude_threshold=1000,
|
||||
landing_descent_trip=10,
|
||||
|
@ -60,6 +61,7 @@ class EmailNotification(object):
|
|||
self.station_position = station_position
|
||||
self.launch_notifications = launch_notifications
|
||||
self.landing_notifications = landing_notifications
|
||||
self.encrypted_sonde_notifications = encrypted_sonde_notifications
|
||||
self.landing_range_threshold = landing_range_threshold
|
||||
self.landing_altitude_threshold = landing_altitude_threshold
|
||||
self.landing_descent_trip = landing_descent_trip
|
||||
|
@ -133,18 +135,44 @@ class EmailNotification(object):
|
|||
}
|
||||
)
|
||||
|
||||
if self.launch_notifications:
|
||||
if "encrypted" in telemetry:
|
||||
if telemetry["encrypted"] and self.encrypted_sonde_notifications:
|
||||
try:
|
||||
# This is a new Encrypted Radiosonde, send an email.
|
||||
msg = "Encrypted Radiosonde Detected:\n"
|
||||
msg += "\n"
|
||||
|
||||
if "subtype" in telemetry:
|
||||
telemetry["type"] = telemetry["subtype"]
|
||||
|
||||
msg += "Serial: %s\n" % _id
|
||||
msg += "Type: %s\n" % telemetry["type"]
|
||||
msg += "Frequency: %s\n" % telemetry["freq"]
|
||||
msg += "Time Detected: %sZ\n" % telemetry["datetime_dt"].isoformat()
|
||||
|
||||
# Construct subject
|
||||
_subject = self.mail_subject
|
||||
_subject = _subject.replace("<id>", telemetry["id"])
|
||||
_subject = _subject.replace("<type>", telemetry["type"])
|
||||
_subject = _subject.replace("<freq>", telemetry["freq"])
|
||||
|
||||
if "encrypted" in telemetry:
|
||||
if telemetry["encrypted"] == True:
|
||||
_subject += " - ENCRYPTED SONDE"
|
||||
|
||||
self.send_notification_email(subject=_subject, message=msg)
|
||||
|
||||
except Exception as e:
|
||||
self.log_error("Error sending E-mail - %s" % str(e))
|
||||
|
||||
elif self.launch_notifications:
|
||||
|
||||
try:
|
||||
# This is a new sonde. Send the email.
|
||||
msg = "Sonde launch detected:\n"
|
||||
msg += "\n"
|
||||
|
||||
if "encrypted" in telemetry:
|
||||
if telemetry["encrypted"] == True:
|
||||
msg += "ENCRYPTED RADIOSONDE DETECTED!\n"
|
||||
|
||||
msg += "Callsign: %s\n" % _id
|
||||
msg += "Serial: %s\n" % _id
|
||||
msg += "Type: %s\n" % telemetry["type"]
|
||||
msg += "Frequency: %s\n" % telemetry["freq"]
|
||||
msg += "Position: %.5f,%.5f\n" % (
|
||||
|
@ -175,10 +203,6 @@ class EmailNotification(object):
|
|||
_subject = _subject.replace("<type>", telemetry["type"])
|
||||
_subject = _subject.replace("<freq>", telemetry["freq"])
|
||||
|
||||
if "encrypted" in telemetry:
|
||||
if telemetry["encrypted"] == True:
|
||||
_subject += " - ENCRYPTED SONDE"
|
||||
|
||||
self.send_notification_email(subject=_subject, message=msg)
|
||||
|
||||
except Exception as e:
|
||||
|
@ -237,7 +261,7 @@ class EmailNotification(object):
|
|||
|
||||
msg = "Nearby sonde landing detected:\n\n"
|
||||
|
||||
msg += "Callsign: %s\n" % _id
|
||||
msg += "Serial: %s\n" % _id
|
||||
msg += "Type: %s\n" % telemetry["type"]
|
||||
msg += "Frequency: %s\n" % telemetry["freq"]
|
||||
msg += "Position: %.5f,%.5f\n" % (
|
||||
|
@ -433,6 +457,29 @@ if __name__ == "__main__":
|
|||
}
|
||||
)
|
||||
|
||||
time.sleep(10)
|
||||
|
||||
print("Testing encrypted sonde alert.")
|
||||
_email_notification.add(
|
||||
{
|
||||
"id": "R1234557",
|
||||
"frame": 10,
|
||||
"lat": 0.0,
|
||||
"lon": 0.0,
|
||||
"alt": 0,
|
||||
"temp": 1.0,
|
||||
"type": "RS41",
|
||||
"subtype": "RS41-SGM",
|
||||
"freq": "401.520 MHz",
|
||||
"freq_float": 401.52,
|
||||
"heading": 0.0,
|
||||
"vel_h": 5.1,
|
||||
"vel_v": -5.0,
|
||||
"datetime_dt": datetime.datetime.utcnow(),
|
||||
"encrypted": True
|
||||
}
|
||||
)
|
||||
|
||||
# Wait a little bit before shutting down.
|
||||
time.sleep(5)
|
||||
|
||||
|
|
|
@ -362,6 +362,9 @@ launch_notifications = True
|
|||
# Send e-mails when a radiosonde is detected descending near your station location
|
||||
landing_notifications = True
|
||||
|
||||
# Send e-mails when an encrypted radiosonde is detected.
|
||||
encrypted_sonde_notifications = True
|
||||
|
||||
# Range threshold for Landing notifications (km from your station location)
|
||||
landing_range_threshold = 30
|
||||
|
||||
|
|
|
@ -363,6 +363,9 @@ launch_notifications = True
|
|||
# Send e-mails when a radiosonde is detected descending near your station location
|
||||
landing_notifications = True
|
||||
|
||||
# Send e-mails when an encrypted radiosonde is detected.
|
||||
encrypted_sonde_notifications = True
|
||||
|
||||
# Range threshold for Landing notifications (km from your station location)
|
||||
landing_range_threshold = 30
|
||||
|
||||
|
|
|
@ -104,8 +104,10 @@ typedef struct {
|
|||
double vH; double vD; double vV;
|
||||
double vx; double vy; double vD2;
|
||||
float T; float RH; float TH; float P;
|
||||
float batV;
|
||||
ui8_t numSV;
|
||||
ui8_t utc_ofs;
|
||||
//ui8_t utc_ofs;
|
||||
ui8_t fwVer;
|
||||
char SN[12+4];
|
||||
ui8_t SNraw[3];
|
||||
ui8_t frame_bytes[FRAME_LEN+AUX_LEN+4];
|
||||
|
@ -193,12 +195,12 @@ frame[0x08..0x0A]: GPS altitude
|
|||
frame[0x0B..0x0E]: GPS hor.Vel. (velE,velN)
|
||||
frame[0x0F..0x11]: GPS TOW
|
||||
frame[0x15]: counter
|
||||
frame[0x16..0x17]: block check
|
||||
|
||||
frame[0x16..0x17]: block check (fwVer < 0x06) ; frame[0x16]: SPI1 P[0] (fwVer >= 0x07), frame[0x17]=0x00
|
||||
frame[0x18..0x19]: GPS ver.Vel. (velU)
|
||||
frame[0x1A..0x1B]: GPS week
|
||||
frame[0x1C..0x1F]: GPS latitude
|
||||
frame[0x20..0x23]: GPS longitude
|
||||
frame[0x24..0x25]: SPI1 P[1..2] (if pressure sensor)
|
||||
|
||||
frame[0x44..0x45]: frame check
|
||||
*/
|
||||
|
@ -218,7 +220,8 @@ frame[0x44..0x45]: frame check
|
|||
#define pos_SN 0x12 // 3 byte
|
||||
#define pos_CNT 0x15 // 1 byte
|
||||
#define pos_BlkChk 0x16 // 2 byte
|
||||
#define pos_Check (stdFLEN-1) // 2 byte
|
||||
#define pos_stdFW 0x43 // 1 byte
|
||||
#define pos_stdCheck (stdFLEN-1) // 2 byte
|
||||
|
||||
#define len_BlkChk 0x16 // frame[0x02..0x17] , incl. chk16
|
||||
|
||||
|
@ -250,6 +253,10 @@ frame[0x44..0x45]: frame check
|
|||
#define col_CSoo "\x1b[38;5;220m"
|
||||
#define col_CSno "\x1b[38;5;1m"
|
||||
#define col_CNST "\x1b[38;5;58m" // 3 byte
|
||||
#define col_ptuP "\x1b[38;5;180m"
|
||||
#define col_ptuT "\x1b[38;5;110m"
|
||||
#define col_ptuU "\x1b[38;5;120m"
|
||||
#define col_ptuTH "\x1b[38;5;115m"
|
||||
|
||||
/*
|
||||
$ for code in {0..255}
|
||||
|
@ -701,18 +708,33 @@ static float get_RH(gpx_t *gpx) {
|
|||
}
|
||||
|
||||
static float get_P(gpx_t *gpx) {
|
||||
// cf. DF9DQ
|
||||
//
|
||||
float hPa = 0.0f;
|
||||
ui16_t val = (gpx->frame_bytes[0x25] << 8) | gpx->frame_bytes[0x24];
|
||||
ui32_t val = (gpx->frame_bytes[0x25] << 8) | gpx->frame_bytes[0x24]; // cf. DF9DQ
|
||||
ui8_t p0 = 0x00;
|
||||
|
||||
if (gpx->fwVer >= 0x07) { // SPI1_P[0]
|
||||
p0 = gpx->frame_bytes[0x16];
|
||||
}
|
||||
val = (val << 8) | p0;
|
||||
|
||||
if (val > 0) {
|
||||
hPa = val/16.0f;
|
||||
hPa = val/(float)(16*256); // 4096=0x1000
|
||||
}
|
||||
|
||||
return hPa;
|
||||
}
|
||||
|
||||
static float get_BatV(gpx_t *gpx) {
|
||||
float batV = 0.0f;
|
||||
ui8_t val = gpx->frame_bytes[0x26]; // cf. DF9DQ
|
||||
|
||||
batV = val * (3.3f/255); // upper 8 bits ADC
|
||||
|
||||
return batV;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
||||
|
@ -741,6 +763,8 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
gpx->P = get_P(gpx); // (optional) pressure
|
||||
}
|
||||
|
||||
gpx->batV = get_BatV(gpx); // battery V
|
||||
|
||||
if ( !gpx->option.slt )
|
||||
{
|
||||
if (gpx->option.col) {
|
||||
|
@ -763,10 +787,11 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
}
|
||||
if (gpx->option.vbs >= 1) {
|
||||
fprintf(stdout, " # ");
|
||||
if (bcOK > 0) fprintf(stdout, " "col_CSok"(ok)"col_TXT);
|
||||
else if (bcOK < 0) fprintf(stdout, " "col_CSoo"(oo)"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"(no)"col_TXT);
|
||||
//
|
||||
if (gpx->fwVer < 0x07) {
|
||||
if (bcOK > 0) fprintf(stdout, " "col_CSok"(ok)"col_TXT);
|
||||
else if (bcOK < 0) fprintf(stdout, " "col_CSoo"(oo)"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"(no)"col_TXT);
|
||||
}
|
||||
if (csOK) fprintf(stdout, " "col_CSok"[OK]"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"[NO]"col_TXT);
|
||||
}
|
||||
|
@ -778,10 +803,14 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
if (gpx->TH > -273.0f) fprintf(stdout, " TH:%.1fC", gpx->TH);
|
||||
}
|
||||
if (gpx->P > 0.0f) {
|
||||
if (gpx->P < 100.0f) fprintf(stdout, " P=%.2fhPa ", gpx->P);
|
||||
else fprintf(stdout, " P=%.1fhPa ", gpx->P);
|
||||
if (gpx->P < 10.0f) fprintf(stdout, " P=%.3fhPa ", gpx->P);
|
||||
else if (gpx->P < 100.0f) fprintf(stdout, " P=%.2fhPa ", gpx->P);
|
||||
else fprintf(stdout, " P=%.1fhPa ", gpx->P);
|
||||
}
|
||||
}
|
||||
if (gpx->option.vbs >= 3 && csOK) {
|
||||
fprintf(stdout, " (bat:%.2fV)", gpx->batV);
|
||||
}
|
||||
fprintf(stdout, ANSI_COLOR_RESET"");
|
||||
}
|
||||
else {
|
||||
|
@ -803,11 +832,12 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
}
|
||||
if (gpx->option.vbs >= 1) {
|
||||
fprintf(stdout, " # ");
|
||||
//if (bcOK) fprintf(stdout, " (ok)"); else fprintf(stdout, " (no)");
|
||||
if (bcOK > 0) fprintf(stdout, " (ok)");
|
||||
else if (bcOK < 0) fprintf(stdout, " (oo)");
|
||||
else fprintf(stdout, " (no)");
|
||||
//
|
||||
if (gpx->fwVer < 0x07) {
|
||||
//if (bcOK) fprintf(stdout, " (ok)"); else fprintf(stdout, " (no)");
|
||||
if (bcOK > 0) fprintf(stdout, " (ok)");
|
||||
else if (bcOK < 0) fprintf(stdout, " (oo)");
|
||||
else fprintf(stdout, " (no)");
|
||||
}
|
||||
if (csOK) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
|
||||
}
|
||||
if (gpx->option.ptu && csOK) {
|
||||
|
@ -818,10 +848,14 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
if (gpx->TH > -273.0f) fprintf(stdout, " TH:%.1fC", gpx->TH);
|
||||
}
|
||||
if (gpx->P > 0.0f) {
|
||||
if (gpx->P < 100.0f) fprintf(stdout, " P=%.2fhPa ", gpx->P);
|
||||
else fprintf(stdout, " P=%.1fhPa ", gpx->P);
|
||||
if (gpx->P < 10.0f) fprintf(stdout, " P=%.3fhPa ", gpx->P);
|
||||
else if (gpx->P < 100.0f) fprintf(stdout, " P=%.2fhPa ", gpx->P);
|
||||
else fprintf(stdout, " P=%.1fhPa ", gpx->P);
|
||||
}
|
||||
}
|
||||
if (gpx->option.vbs >= 3 && csOK) {
|
||||
fprintf(stdout, " (bat:%.2fV)", gpx->batV);
|
||||
}
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
@ -846,6 +880,7 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
if (gpx->RH > -0.5f) fprintf(stdout, ", \"humidity\": %.1f", gpx->RH );
|
||||
if (gpx->P > 0.0f) fprintf(stdout, ", \"pressure\": %.2f", gpx->P );
|
||||
}
|
||||
fprintf(stdout, ", \"batt\": %.2f", gpx->batV);
|
||||
fprintf(stdout, ", \"rawid\": \"M20_%02X%02X%02X\"", gpx->frame_bytes[pos_SN], gpx->frame_bytes[pos_SN+1], gpx->frame_bytes[pos_SN+2]); // gpx->type
|
||||
fprintf(stdout, ", \"subtype\": \"0x%02X\"", gpx->type);
|
||||
if (gpx->jsn_freq > 0) {
|
||||
|
@ -876,6 +911,8 @@ static int print_frame(gpx_t *gpx, int pos, int b2B) {
|
|||
int cs1, cs2;
|
||||
int bc1, bc2, bc;
|
||||
int flen = stdFLEN; // stdFLEN=0x64, auxFLEN=0x76; M20:0x45 ?
|
||||
int pos_fw = pos_stdFW;
|
||||
int pos_check = pos_stdCheck;
|
||||
|
||||
if (b2B) {
|
||||
bits2bytes(gpx->frame_bits, gpx->frame_bytes);
|
||||
|
@ -885,10 +922,21 @@ static int print_frame(gpx_t *gpx, int pos, int b2B) {
|
|||
else {
|
||||
gpx->auxlen = flen - stdFLEN;
|
||||
//if (gpx->auxlen < 0 || gpx->auxlen > AUX_LEN) gpx->auxlen = 0; // 0x43,0x45
|
||||
if (gpx->auxlen < 0) {
|
||||
gpx->auxlen = 0;
|
||||
pos_fw = flen-2; // only if flen < stdFLEN
|
||||
}
|
||||
else if (gpx->auxlen > AUX_LEN) {
|
||||
gpx->auxlen = AUX_LEN;
|
||||
flen = stdFLEN+AUX_LEN;
|
||||
}
|
||||
}
|
||||
pos_check = flen-1;
|
||||
gpx->fwVer = gpx->frame_bytes[pos_fw];
|
||||
if (gpx->fwVer > 0x20) gpx->fwVer = 0;
|
||||
|
||||
cs1 = (gpx->frame_bytes[pos_Check+gpx->auxlen] << 8) | gpx->frame_bytes[pos_Check+gpx->auxlen+1];
|
||||
cs2 = checkM10(gpx->frame_bytes, pos_Check+gpx->auxlen);
|
||||
cs1 = (gpx->frame_bytes[pos_check] << 8) | gpx->frame_bytes[pos_check+1];
|
||||
cs2 = checkM10(gpx->frame_bytes, pos_check);
|
||||
|
||||
bc1 = (gpx->frame_bytes[pos_BlkChk] << 8) | gpx->frame_bytes[pos_BlkChk+1];
|
||||
bc2 = blk_checkM10(len_BlkChk, gpx->frame_bytes+2); // len(essentialBlock+chk16) = 0x16
|
||||
|
@ -921,16 +969,27 @@ static int print_frame(gpx_t *gpx, int pos, int b2B) {
|
|||
if ((i >= pos_GPSvU) && (i < pos_GPSvU+2)) fprintf(stdout, col_GPSvel);
|
||||
if ((i >= pos_SN) && (i < pos_SN+3)) fprintf(stdout, col_SN);
|
||||
if (i == pos_CNT) fprintf(stdout, col_CNT);
|
||||
if ((i >= pos_BlkChk) && (i < pos_BlkChk+2)) fprintf(stdout, col_Check);
|
||||
if ((i >= pos_Check+gpx->auxlen) && (i < pos_Check+gpx->auxlen+2)) fprintf(stdout, col_Check);
|
||||
if (gpx->fwVer < 0x07) {
|
||||
if ((i >= pos_BlkChk) && (i < pos_BlkChk+2)) fprintf(stdout, col_Check);
|
||||
} else {
|
||||
if ((i >= pos_BlkChk+1) && (i < pos_BlkChk+2)) fprintf(stdout, col_Check);
|
||||
}
|
||||
if (i >= 0x02 && i <= 0x03) fprintf(stdout, col_ptuU);
|
||||
if (i >= 0x04 && i <= 0x05) fprintf(stdout, col_ptuT);
|
||||
if (i >= 0x06 && i <= 0x07) fprintf(stdout, col_ptuTH);
|
||||
if (i == 0x16 && gpx->fwVer >= 0x07 || i >= 0x24 && i <= 0x25) fprintf(stdout, col_ptuP);
|
||||
|
||||
if ((i >= pos_check) && (i < pos_check+2)) fprintf(stdout, col_Check);
|
||||
fprintf(stdout, "%02x", byte);
|
||||
fprintf(stdout, col_FRTXT);
|
||||
}
|
||||
if (gpx->option.vbs) {
|
||||
fprintf(stdout, " # "col_Check"%04x"col_FRTXT, cs2);
|
||||
if (bc > 0) fprintf(stdout, " "col_CSok"(ok)"col_TXT);
|
||||
else if (bc < 0) fprintf(stdout, " "col_CSoo"(oo)"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"(no)"col_TXT);
|
||||
if (gpx->fwVer < 0x07) {
|
||||
if (bc > 0) fprintf(stdout, " "col_CSok"(ok)"col_TXT);
|
||||
else if (bc < 0) fprintf(stdout, " "col_CSoo"(oo)"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"(no)"col_TXT);
|
||||
}
|
||||
if (cs1 == cs2) fprintf(stdout, " "col_CSok"[OK]"col_TXT);
|
||||
else fprintf(stdout, " "col_CSno"[NO]"col_TXT);
|
||||
}
|
||||
|
@ -943,9 +1002,11 @@ static int print_frame(gpx_t *gpx, int pos, int b2B) {
|
|||
}
|
||||
if (gpx->option.vbs) {
|
||||
fprintf(stdout, " # %04x", cs2);
|
||||
if (bc > 0) fprintf(stdout, " (ok)");
|
||||
else if (bc < 0) fprintf(stdout, " (oo)");
|
||||
else fprintf(stdout, " (no)");
|
||||
if (gpx->fwVer < 0x07) {
|
||||
if (bc > 0) fprintf(stdout, " (ok)");
|
||||
else if (bc < 0) fprintf(stdout, " (oo)");
|
||||
else fprintf(stdout, " (no)");
|
||||
}
|
||||
if (cs1 == cs2) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
|
Ładowanie…
Reference in New Issue