Changeset 11130 in ntrip for trunk/BNC/tests/tools
- Timestamp:
- Oct 28, 2026, 9:32:30 AM (3 days ago)
- Location:
- trunk/BNC/tests/tools
- Files:
-
- 4 edited
-
bncraw.py (modified) (3 diffs)
-
fakecaster.py (modified) (8 diffs)
-
mkcrafted.py (modified) (6 diffs)
-
ssr_harness.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/tests/tools/bncraw.py
r11127 r11130 197 197 198 198 199 def frame(payload): 200 """RTCM3 frame (preamble, length, payload, CRC24Q) of a payload.""" 201 head = bytes([0xD3, (len(payload) >> 8) & 0x03, len(payload) & 0xFF]) 202 return head + payload + crc24q(head + payload).to_bytes(3, "big") 203 204 199 205 def cmd_slice(args): 200 206 stations = set(args.stations.split(",")) if args.stations else None 207 types = args.types.split(",") if args.types else None 208 parsers = {} 201 209 202 210 def selected(): … … 208 216 if args.end and t >= args.end: 209 217 continue 218 if types: 219 # keep only the RTCM3 messages of the given types (or type prefixes) 220 frames = parsers.setdefault(sta, Rtcm3Framer()).feed(data) 221 kept = b"".join(frame(pl) for pl in frames 222 if any(msg_type(pl).startswith(tt) for tt in types)) 223 if not kept: 224 continue 225 data = kept 210 226 yield t, sta, fmt, data 211 227 … … 245 261 p.add_argument("--end", help="ISO time, exclusive") 246 262 p.add_argument("--stations", help="comma separated staIDs to keep") 263 p.add_argument("--types", help="comma separated RTCM3 message types or prefixes to keep, " 264 "e.g. 1019,4076_02 (GPS ephemerides and IGS-SSR GPS messages)") 247 265 p.set_defaults(func=cmd_slice) 248 266 -
trunk/BNC/tests/tools/fakecaster.py
r11127 r11130 15 15 additionally requires a client certificate signed by that CA. With --serve 16 16 a GET request (BNC as Ntrip client) is answered with the RTCM bytes of the 17 given raw file. Failed TLS handshakes are reported on stdout. 17 given raw file. With --reply an upload is answered with this text instead 18 of the 200 status (e.g. a rejection), and the connection is closed. Failed 19 TLS handshakes are reported on stdout. 18 20 """ 19 21 … … 55 57 self.total = 0 56 58 self.handshakes = 0 59 self.rejected = 0 57 60 self.served = 0 58 61 … … 67 70 68 71 69 def serve(conn, store, timeout, tls=None, served=None): 72 def serve(conn, store, timeout, tls=None, served=None, reply=None): 70 73 conn.settimeout(timeout) 71 74 buf = b"" … … 89 92 b"Content-Type: gnss/data\r\nConnection: close\r\n\r\n" + served) 90 93 store.served += len(served) 94 return 95 if reply is not None: 96 conn.sendall(reply) 97 store.rejected += 1 91 98 return 92 99 if header.startswith(b"SOURCE"): … … 127 134 ap.add_argument("--tls-client-ca", help="require a client certificate of this CA") 128 135 ap.add_argument("--serve", help="raw file whose RTCM bytes are sent on GET") 136 ap.add_argument("--reply", help="answer to uploads instead of 200 ('\\r\\n' escapes allowed)") 129 137 args = ap.parse_args() 130 138 … … 136 144 tls.verify_mode = ssl.CERT_REQUIRED 137 145 tls.load_verify_locations(args.tls_client_ca) 146 reply = None 147 if args.reply is not None: 148 reply = args.reply.encode("latin-1").decode("unicode_escape").encode("latin-1") 138 149 served = None 139 150 if args.serve: … … 155 166 except socket.timeout: 156 167 break 157 t = threading.Thread(target=serve, args=(conn, store, args.timeout, tls, served), 168 t = threading.Thread(target=serve, args=(conn, store, args.timeout, tls, served, reply), 158 169 daemon=True) 159 170 t.start() … … 166 177 if served is not None: 167 178 print("served %d bytes" % store.served, flush=True) 179 if reply is not None: 180 print("%d upload(s) answered with --reply" % store.rejected, flush=True) 168 181 return 0 169 182 -
trunk/BNC/tests/tools/mkcrafted.py
r11125 r11130 6 6 CRAFT0IGS0 IGS-SSR VTEC (4076/201), decoded by SsrCorrIgs, followed by 7 7 RTCM 1300/1301/1302 with 31-character names (BNC's RTCM scan 8 lists them only for streams that also decode successfully) 8 lists them only for streams that also decode successfully); 9 in the first epoch also two RTCM 1033 (antenna and receiver 10 descriptors): a complete one and one whose receiver descriptor 11 length (200) runs beyond the end of the message 9 12 CRAFT0RTC0 RTCM-SSR VTEC (1264), decoded by SsrCorrRtcm 10 13 CRAFT0NEW0 new RTCM-SSR metadata (60), not dispatched by BNC at present; … … 12 15 - 7 entries (maximum), additional parameter of 40 and 0 bits 13 16 - 31 entries (5-bit count, more than META_MAXNUMENTRIES=7) 17 and satellite antenna messages (DF+010-DF+021): 18 - BDS (83): C01, C17, C33, C49, C64 (mask bits in all four 19 16-bit quarters of DF394), individual blocks 20 - GPS (80): G01, G02, G32 sharing one block and one frequency 21 block; nadir angle corrections incl. the invalid value 14 22 15 23 VTEC epochs (every 5 s): … … 22 30 by eye; the heights are 100 km * layer number. 23 31 32 With --rawfile, a raw file with hostile chunk headers is written instead 33 (test of the raw file reader, data/crafted_rawfile.raw): 34 ../ESCAPE0 station ID with a path: RTCM-SSR VTEC whose .ssr file must be 35 written inside the output directory 36 CRAFT0RTC0 RTCM-SSR VTEC, 5 s later 37 then a chunk header announcing 2000000000 bytes, which must be rejected 38 24 39 Usage: mkcrafted.py <out.raw> 40 mkcrafted.py --rawfile <out.raw> 25 41 """ 26 42 … … 140 156 141 157 158 def descriptors(strings, truncate=False): 159 """RTCM 1033: antenna, setup ID, serial, receiver, firmware, serial.""" 160 w = BitWriter() 161 w.u(1033, 12) 162 w.u(0, 12) # reference station ID 163 ant, antser, rec, firm, recser = strings 164 w.text(ant, 8) 165 w.u(0, 8) # antenna setup ID 166 w.text(antser, 8) 167 if truncate: 168 w.u(200, 8) # receiver descriptor length beyond the message 169 for c in rec.encode("ascii"): 170 w.u(c, 8) 171 else: 172 w.text(rec, 8) 173 w.text(firm, 8) 174 w.text(recser, 8) 175 return frame(w.payload()) 176 177 142 178 def metadata(entries): 143 179 """entries: list of None (default model) or number of additional bits.""" … … 163 199 164 200 201 def antenna(msg, sats, shared, nadir): 202 """Satellite antenna message; sats: PRNs (1..64) of the mask.""" 203 w = BitWriter() 204 w.u(msg, 12) 205 w.u(4711, 16) # provider ID 206 w.u(5, 6) # satellite antenna IOD 207 w.u(1, 1) # phase center information 208 w.u(0, 1) # group delay information 209 w.u(1, 1) # nadir angle dependent corrections follow 210 w.u(3, 5) # maximum off-nadir angle: corrections 0..3 deg 211 w.u(1, 4) # range extension: 3 + 1 = 4 bits 212 w.u(shared, 1) # satellite set indicator 213 mask = 0 214 for prn in sats: 215 mask |= 1 << (64 - prn) 216 w.u(mask, 64) 217 for n in range(1 if shared else len(sats)): 218 w.u(shared, 1) # frequency set indicator 219 w.u(0b101000, 6) # frequencies 0 and 2 220 for f in range(1 if shared else 2): 221 w.u(1, 1) # nadir correction follows 222 w.s(100 * n + 10 * f + 1, 12) # mm 223 for deg in range(4): 224 w.s(nadir[(n + f + deg) % len(nadir)], 4) # mm, -8: invalid 225 return frame(w.payload()) 226 227 228 def rawfile(path): 229 chunks = [] 230 for i, sta in enumerate(["../ESCAPE0", "CRAFT0RTC0"]): 231 t = T0 + datetime.timedelta(seconds=5 * i) 232 chunks.append((t.isoformat(), sta, "RTCM_3", vtec_rtcm(t, [(2, 2)]))) 233 write_chunks(path, chunks) 234 t = T0 + datetime.timedelta(seconds=10) 235 with open(path, "ab") as o: 236 o.write(("%s CRAFT0RTC0 RTCM_3 2000000000\n" % t.isoformat()).encode()) 237 o.write(vtec_rtcm(t, [(2, 2)]) + b"\n") 238 239 165 240 def main(): 241 if len(sys.argv) == 3 and sys.argv[1] == "--rawfile": 242 rawfile(sys.argv[2]) 243 return 166 244 if len(sys.argv) != 2: 167 245 sys.exit(__doc__) … … 175 253 t = T0 + datetime.timedelta(seconds=5 * i) 176 254 stamp = t.isoformat() 177 chunks.append((stamp, "CRAFT0IGS0", "RTCM_3", vtec_igs(t, layers) 178 + service_crs() + helmert() + rtcm_crs())) 255 data = vtec_igs(t, layers) + service_crs() + helmert() + rtcm_crs() 256 if i == 0: 257 data += descriptors(["LEIAR25.R4 LEIT", "12345", "SEPT POLARX5", 258 "5.5.0", "3001234"]) 259 data += descriptors(["TRUNCATED ANTENNA", "9", "RECEIVER", "", ""], 260 truncate=True) 261 chunks.append((stamp, "CRAFT0IGS0", "RTCM_3", data)) 179 262 chunks.append((stamp, "CRAFT0RTC0", "RTCM_3", vtec_rtcm(t, layers))) 180 263 stamp = (T0 + datetime.timedelta(seconds=15)).isoformat() 181 264 chunks.append((stamp, "CRAFT0NEW0", "RTCM_3", 182 metadata([40, 0] + [None] * 5) + metadata([None] * 31))) 265 metadata([40, 0] + [None] * 5) + metadata([None] * 31) 266 + antenna(83, [1, 17, 33, 49, 64], 0, [-7, 0, 7, 3]) 267 + antenna(80, [1, 2, 32], 1, [5, -8, -1, 2]))) 183 268 write_chunks(sys.argv[1], chunks) 184 269 -
trunk/BNC/tests/tools/ssr_harness.cpp
r11127 r11130 7 7 // reported by AddressSanitizer instead of silently corrupting the next member. 8 8 // 9 // Every decoded VTEC (all formats) and metadata message (new RTCM-SSR) is 10 // encoded again with the Make* function of the same class and decoded once 11 // more; the result must be identical (exit code 1 otherwise). 9 // Every decoded VTEC (all formats), metadata and satellite antenna message 10 // (new RTCM-SSR) is encoded again with the Make* function of the same class 11 // and decoded once more; the result must be identical, for the antenna 12 // messages also the bytes of the frame (exit code 1 otherwise). 12 13 // 13 14 // Usage: ssr_harness <file> (BNC raw file or plain RTCM3 byte stream) … … 96 97 int irc = t1.decode(ssr, frame, size); 97 98 printf(" %-8s irc %3d", name, irc); 99 SsrCorrRtcmNew* rtcmNew = dynamic_cast<SsrCorrRtcmNew*>(ssr); 98 100 if (irc >= 0 && t1.v->NumLayers) { 99 101 double sum = 0.0; … … 125 127 } 126 128 } 127 SsrCorrRtcmNew* rtcmNew = dynamic_cast<SsrCorrRtcmNew*>(ssr);128 129 if (rtcmNew) { 129 130 char buffer[CLOCKORBIT_BUFFERSIZE]; … … 134 135 nFailed += !ok; 135 136 } 137 } 138 for (unsigned s = 0; rtcmNew && irc >= 0 && s < CLOCKORBIT_SATNUM; s++) { 139 if (!t1.a->SatelliteMask[s]) { 140 continue; 141 } 142 printf(" ANT type %u mask %016llx", t1.a->messageType[s], 143 (unsigned long long)t1.a->SatelliteMask[s]); 144 char buffer[CLOCKORBIT_BUFFERSIZE]; 145 size_t len = rtcmNew->MakeAntenna(t1.a, t1.a->messageType[s], buffer, sizeof(buffer)); 146 t_target t2; 147 bool sameBytes = len == size && memcmp(buffer, frame, size) == 0; 148 bool ok = len > 0 && t2.decode(ssr, (const unsigned char*)buffer, len) >= 0 && 149 memcmp(t1.a, t2.a, sizeof(*t1.a)) == 0; 150 printf(" re-encoded: %s, %s", ok ? "identical" : "DIFFERENT", 151 sameBytes ? "same bytes" : "OTHER BYTES"); 152 nFailed += !ok || !sameBytes; 136 153 } 137 154 printf("\n");
Note:
See TracChangeset
for help on using the changeset viewer.
