Porównaj commity

...

309 Commity

Autor SHA1 Wiadomość Data
Mark Jessop ea608f4ba0 Add 3 v2 IDs 2024-05-12 21:08:00 +09:30
Mark Jessop 5366134aac add V2 ID 2024-05-12 15:34:38 +09:30
Mark Jessop 8fde8b9ad2 Add PD7BOR 2024-05-10 09:18:35 +09:30
Mark Jessop 4439fbc430 add DL1BRF 2024-05-08 07:44:17 +09:30
Mark Jessop 3660d0cc7c Add VK5ARG id 2024-05-07 17:59:26 +09:30
Mark Jessop 60b88fd495 Add custom fields for SKPQKM 2024-05-07 07:54:00 +09:30
Mark Jessop 9df66628a4 Add 2 V2 IDs 2024-05-05 07:17:56 +09:30
Mark Jessop 7f098068bb Add SP9WAK 2024-05-03 22:17:27 +09:30
Mark Jessop 744e0e7071 add 2 V2 IDs 2024-05-02 07:52:25 +09:30
Mark Jessop f094c0c0ce Add 4 V2 IDs 2024-05-01 08:07:17 +09:30
Mark Jessop d00d984e78 Add 9A4GE-3 2024-04-30 20:57:48 +09:30
Mark Jessop eb911c8c0e add 4 new v2 IDs 2024-04-30 07:58:59 +09:30
Mark Jessop df1b81fc41 Add Party-Time 2024-04-26 17:36:33 +09:30
Mark Jessop 24f34fe6cd add SQ2CPA 2024-04-23 07:54:04 +09:30
Mark Jessop fa959febea Add more DG4CG IDs 2024-04-22 20:04:30 +09:30
Mark Jessop 2aa0dda4bb add Martinus-MZ 2024-04-22 07:48:49 +09:30
Mark Jessop 0956b08d36 Add AK3F 2024-04-20 20:30:44 +09:30
Mark Jessop 1265b069eb Add DG4CG-1 2024-04-20 18:45:26 +09:30
Mark Jessop fdae85612c Add DG4CG-2/3 2024-04-19 23:07:58 +09:30
Mark Jessop d3e8e903c9 Add StratoSoar 2024-04-18 08:15:45 +09:30
Mark Jessop 3311211ef6
Merge pull request #231 from sp6qkm/patch-8
Update payload_id_list.txt
2024-04-15 07:16:13 +09:30
sp6qkm 1e2ef897c7
Update payload_id_list.txt
Add:  ID 553 SQ6DAG
2024-04-14 19:50:06 +02:00
Mark Jessop afd180be66 add PA3ADE-KITE 2024-04-11 21:19:06 +09:30
Mark Jessop 7ab762727e rename PE1NW to PD1NW 2024-04-11 18:32:16 +09:30
Mark Jessop 5f7475b56d add PE1NW 2024-04-10 23:28:56 +09:30
Mark Jessop d4cbfa4998 Add F4KLR 2024-04-07 08:25:40 +09:30
Mark Jessop 202454bf44 Allow decoding of negative frequencies, add triple rx script 2024-04-06 10:14:32 +10:30
Mark Jessop dd40912fc8 Rename OLHZN to KD2KPZ 2024-04-05 23:34:40 +10:30
Mark Jessop c85f8d3260 add OLHZN 2024-04-05 22:54:20 +10:30
Mark Jessop 61aa309389 add 9A3SWO 2024-04-04 17:39:55 +10:30
Mark Jessop bb75540904 Add KB3ZOX-2 2024-04-02 07:59:34 +10:30
Mark Jessop 02058a6d38 Add SP9RKF 2024-03-24 13:54:47 +10:30
Mark Jessop b9d370df7e Add SP7XSS-2 2024-03-23 18:22:27 +10:30
Mark Jessop bc67f77121 Add SP7XSS 2024-03-22 23:33:12 +10:30
Mark Jessop 03b7abc6c7 add Xpico 2024-03-19 07:55:38 +10:30
Mark Jessop 0445e2d569 Add PD1EG 2024-03-11 09:20:57 +10:30
Mark Jessop 189a0b23e5 add F1AQE 2024-03-07 07:47:58 +10:30
Mark Jessop b0a7df7336 Add 9a4ge-2 2024-03-02 09:11:09 +10:30
Mark Jessop 64b477f17a Add 2 V2 IDs 2024-02-27 07:40:15 +10:30
Mark Jessop b26ab6ab14 add PA3EIV 2024-02-26 08:51:51 +10:30
Mark Jessop 6b28a30bbe add KE2CBS 2024-02-25 14:11:15 +10:30
Mark Jessop 6b7a6bf21f add custom data for SP9SKP 2024-02-25 09:07:01 +10:30
Mark Jessop 5818abc1fc Add F6AGV-BHAF 2024-02-24 16:51:18 +10:30
Mark Jessop d6ba4e95f9 Add 2 V2 IDs 2024-02-23 22:13:22 +10:30
Mark Jessop 256228b107 add KJ0RE 2024-02-21 07:56:24 +10:30
Mark Jessop c9b3104cd0 Add DG4CG 2024-02-19 07:48:07 +10:30
Mark Jessop da46126062
Merge pull request #217 from sp6qkm/patch-7
Update payload_id_list.txt
2024-02-18 08:07:42 +10:30
sp6qkm f70d7bbb79
Update payload_id_list.txt
Hello Mark, could I ask you to accept the added IDs:
525, SP6QKM
526, SP8KDE
527, SQ8AOL
528, SQ9AOL
529, NANO-1
530, SKPQKM

Thank you in advance
2024-02-17 20:21:37 +01:00
Mark Jessop 997261377c Add v2 id 2024-02-17 09:31:54 +10:30
Mark Jessop a88afd4f4e Add 2 v2 IDs 2024-02-13 11:31:28 +10:30
Mark Jessop 562525088c ADd PD3T 2024-02-09 12:34:32 +10:30
Mark Jessop a916fab44d Add 3 V2 IDs 2024-02-09 07:58:05 +10:30
Mark Jessop 794a2c1e5a Add NEC_CQ73 2024-02-05 20:18:18 +10:30
Mark Jessop cfef63cb29 Add IT9EWK 2024-02-05 17:03:26 +10:30
Mark Jessop a63f1c9488 Add v2 ID 2024-02-05 17:02:50 +10:30
Mark Jessop 367fc797c7 add RXSONDE 2024-02-04 18:48:11 +10:30
Mark Jessop 5f63666f5f Handle 202 responses from Sondehub better. 2024-02-03 15:56:02 +10:30
Mark Jessop 80121545f3
Merge pull request #209 from xssfox/vk3fur
Add VK3FUR payload id
2024-02-03 14:29:24 +10:30
xssfox d38e55de42 Add VK3FUR payload id 2024-02-03 14:55:41 +11:00
Mark Jessop 0e3df15067 Add testing script to payloads module 2024-01-31 11:51:06 +10:30
Mark Jessop aa0ebdf6d1 Fix DF7PM custom fields 2024-01-31 07:32:50 +10:30
Mark Jessop 18726f6d5f Add DF7PN custom fields 2024-01-30 18:09:51 +10:30
Mark Jessop fd6adaa7cb Add IZ0CGP 2024-01-25 21:11:22 +10:30
Mark Jessop 7790a7dd66 Add IU0MUN 2024-01-25 19:48:08 +10:30
Mark Jessop ff75d157db Add F4EHY 2024-01-21 10:13:58 +10:30
Mark Jessop 1494277fb9 Add DL1XH 2024-01-18 10:29:49 +10:30
Mark Jessop 62c094e697 Add ICARO 2024-01-15 16:09:20 +10:30
Mark Jessop 1a7e30cd16 add IW1DBF 2024-01-12 08:58:31 +10:30
Mark Jessop 384a6ebc5e add G8FJG 2024-01-10 07:46:35 +10:30
Mark Jessop 44ea165663 Add 2 V2 IDs 2024-01-08 07:56:05 +10:30
Mark Jessop 9ab5b88786
Merge pull request #205 from sp6qkm/patch-5
Update payload_id_list.txt
2024-01-08 07:07:19 +10:30
sp6qkm 7d95fa890f
Update payload_id_list.txt
Could I ask you to add a new ID : 502, SN32WOSP
2024-01-07 21:26:59 +01:00
Mark Jessop d982fad0e7 Add KD2EAT-DFM ID and Custom fields 2023-12-30 14:35:25 +10:30
Mark Jessop 36a938f68a Added V2 ID 2023-12-30 09:17:56 +10:30
Mark Jessop ee97011d95
Merge pull request #200 from sp6qkm/patch-4
Update payload_id_list.txt
2023-12-29 08:16:57 +10:30
sp6qkm 3fbe8de5b9
Update payload_id_list.txt 2023-12-28 21:31:40 +01:00
Mark Jessop 6d04e36909 Add SP6ZWR 2023-12-21 19:58:53 +10:30
Mark Jessop 390c73cafa change PE1PSI to Flybag-2 2023-12-19 08:29:18 +10:30
Mark Jessop f79c810a22 add SP9SKP 2023-12-18 20:40:50 +10:30
Mark Jessop a5c22243e9 Update v2 IDs 2023-12-17 08:41:50 +10:30
Mark Jessop 68f03a1eab add DC1NSK 2023-12-15 07:56:54 +10:30
Mark Jessop 38b394ee17 add 3 v2 IDs 2023-12-13 07:54:08 +10:30
Mark Jessop 681ff9e554 add 2 v2 IDs 2023-12-12 16:07:47 +10:30
Mark Jessop 0fc090c757 add AJ4XE custom fields 2023-12-08 08:17:50 +10:30
Mark Jessop 05b9e90650 Add F5IKO 2023-12-05 21:26:11 +10:30
Mark Jessop ea04c308cd Add 2 V2 IDs 2023-12-04 07:58:21 +10:30
Mark Jessop d1eec81173 Add many new IDs 2023-12-01 08:13:04 +10:30
Mark Jessop 804a42d9f9 Add 2 v2 IDs 2023-11-26 19:07:26 +10:30
Mark Jessop de74cc4a1a Add WJ2B 2023-11-23 07:54:56 +10:30
Mark Jessop f7d5d54bf6 add AJ4XE 2023-11-20 07:02:02 +10:30
Mark Jessop 197b481914 Add FlightKW 2023-11-17 09:02:32 +10:30
Mark Jessop 7ba9d50946 Add COSMO-PK 2023-11-14 07:54:10 +10:30
Mark Jessop 0a7ef43e1b add OK1RAJ 2023-11-04 16:44:40 +10:30
Mark Jessop e0f140eae7 add 2E0NNF 2023-11-01 08:04:03 +10:30
Mark Jessop a096a1af9a add K4KDR 2023-10-30 16:31:57 +10:30
Mark Jessop e0c584f616 Add OH7FES 2023-10-28 09:26:33 +10:30
Mark Jessop 46835b3d55
Merge pull request #188 from cixio/master
Update payload_id_list.txt
2023-10-27 17:47:50 +10:30
cixio 4abbcbdfb9 Update payload_id_list.txt 2023-10-27 09:09:39 +02:00
Mark Jessop 71981aed87 add DB7XO 2023-10-25 07:55:23 +10:30
Mark Jessop 82dcae13b4 Add PD2JM 2023-10-09 07:54:00 +10:30
Mark Jessop ac2efeada7 Initial starts of encoder functionality, wrappers for horuslib l2 functions 2023-09-29 11:40:13 +09:30
Mark Jessop fb694d78ce DK0WT-V2 2023-09-29 08:59:42 +09:30
Mark Jessop 78b5847da8 Add DK0WT 2023-09-29 08:41:39 +09:30
Mark Jessop b67e8ee46b Change PD3EGE to SPECTRE 2023-09-27 08:18:42 +09:30
Mark Jessop 8278436333
Merge pull request #185 from a-a/master
Update payload_id_list.txt
2023-09-26 08:29:08 +09:30
Jade M7NGO 7295d8bc53 add M7NGO 2023-09-25 21:29:20 +01:00
Mark Jessop 680acafdfb add KM6OIR 2023-09-22 08:05:49 +09:30
Mark Jessop c94a9f758d add flightdesign payload IDs 2023-09-15 17:51:07 +09:30
Mark Jessop 9548a23d07 add SP4CE 2023-09-09 07:43:29 +09:30
Mark Jessop 4b57a65385 add KE2BOK 2023-09-04 07:04:11 +09:30
Mark Jessop 67f7626ab8 Add 2 V2 IDs 2023-08-31 07:53:53 +09:30
Mark Jessop 3198663109 Add DL6PI 2023-08-26 19:32:02 +09:30
Mark Jessop 28904aa5b4 add PA0CAB 2023-08-23 09:06:44 +09:30
Mark Jessop 2c7c7c4251 Add KI5RZY 2023-08-22 12:49:26 +09:30
Mark Jessop 158b2e3354 update DL1MRZ 2023-08-19 09:21:17 +09:30
Mark Jessop 4fbc574979 add DL1MRZ 2023-08-15 08:19:59 +09:30
Mark Jessop e02e38e8d4 Add SOLARBAG 2023-08-10 17:11:34 +09:30
Mark Jessop 948e97b3eb Narrow allowed payload-system time window, add warnings for various issues. 2023-07-28 21:30:06 +09:30
Mark Jessop 5f2d8416f1 add O38 2023-07-22 18:47:04 +09:30
Mark Jessop 6768c53397 add VI25AREG 2023-07-16 10:16:33 +09:30
Mark Jessop c8ce3cc6aa add KB4RKS 2023-07-15 08:06:40 +09:30
Mark Jessop 6dda766205 added SP5YAM 2023-07-09 17:16:29 +09:30
Mark Jessop 6faffa18aa Add SP5WWL 2023-07-09 15:48:04 +09:30
Mark Jessop c7c5a6eb5d Upload speed field to sondehub 2023-07-08 10:21:49 +09:30
Mark Jessop dad39621f0 Add F8DKG 2023-07-07 07:43:35 +09:30
Mark Jessop b1459c68c8 Add DJ9AS 2023-07-07 07:37:45 +09:30
Mark Jessop 40559e1d62 Add SNSF01 2023-07-01 12:24:15 +09:30
Mark Jessop 7982bda6e7 Add JOTACross IDs 2023-06-23 08:03:15 +09:30
Mark Jessop ce137dba70 Add SP3ET-2 2023-06-22 07:18:01 +09:30
Mark Jessop 10a7e90382 add MONASAT 2023-06-20 07:21:50 +09:30
Mark Jessop e0e3203280 Add W1U 2023-06-19 07:53:15 +09:30
Mark Jessop 88a04ea691 Add Horus V2 packet format diagram 2023-06-14 15:17:00 +10:00
Mark Jessop 7574b10d59 Add Horus V2 packet format diagram 2023-06-14 15:14:09 +10:00
Mark Jessop 8c6bdd29a2 Add SOLflight 2023-06-10 17:50:28 +09:30
Mark Jessop d1cd35e36d add SQ3XBD 2023-06-04 09:03:34 +09:30
Mark Jessop 1759df560c add HG8LXL 2023-06-03 11:23:12 +09:30
Mark Jessop 652300bb24 add SP3ZHP 2023-06-02 09:35:34 +09:30
Mark Jessop 72e7e4923a added KN6ZTT 2023-05-31 07:09:08 +09:30
Mark Jessop 4a1597cda6 PD5MF -> PA5MF 2023-05-25 17:11:48 +09:30
Mark Jessop 6258bcc33e add SP5GFN 2023-05-25 07:07:36 +09:30
Mark Jessop c8e83cf998 add DO5IO 2023-05-24 18:46:27 +09:30
Mark Jessop 6a3718a715 Add OM2OFA IDs 2023-05-18 23:10:15 +09:30
Mark Jessop 9fb4baeb4b Add 2 new v2 IDs 2023-05-18 11:25:22 +09:30
Mark Jessop 333cc8f58e add SQ5RB 2023-05-17 08:04:50 +09:30
Mark Jessop 7abf447200 Add 9A7DI 2023-05-16 19:36:00 +09:30
Mark Jessop fe9ca5fbcb Add SP5LOT 2023-05-13 08:22:12 +09:30
Mark Jessop 8f322bee50 add 4x v2 IDs 2023-05-12 09:24:35 +09:30
Mark Jessop 7f881692d7 add W1STR 2023-05-04 09:00:11 +09:30
Mark Jessop cea3b37230 add DM2DL 2023-05-03 07:53:34 +09:30
Mark Jessop 28f35909b2 add HA8LOU 2023-05-01 08:31:31 +09:30
Mark Jessop 956608e76e Change JMSS to VK3DNS-JMSS 2023-04-29 13:06:40 +09:30
Mark Jessop f069764fc6 add JMSS 2023-04-29 12:48:24 +09:30
Mark Jessop 43abc6d08f add SP7AR 2023-04-27 20:07:54 +09:30
Mark Jessop 1bc30e2310 Merge branch 'master' of github.com:projecthorus/horusdemodlib 2023-04-26 08:15:07 +09:30
Mark Jessop 503f392002 add IW1DBF 2023-04-26 08:03:08 +09:30
Mark Jessop 34d90a6df5
Merge pull request #150 from mikaelnousiainen/patch-1
Set custom fields for OH3HAB-4FSK-V2
2023-04-25 16:19:27 +09:30
Mikael Nousiainen 5ed247dc30
Set custom fields for OH3HAB-4FSK-V2 2023-04-25 09:48:06 +03:00
Mark Jessop 138449d7aa Add W3YP-2 2023-04-19 07:10:16 +09:30
Mark Jessop c944da0bf2 add OH3CUF 2023-04-18 17:32:05 +09:30
Mark Jessop e5842a6710
Merge pull request #148 from sp6qkm/patch-3
Update payload_id_list.txt
2023-04-14 07:07:02 +09:30
sp6qkm 712bbdd27b
Update payload_id_list.txt
Please add ID: 401 SP6ONZ
2023-04-13 18:32:20 +02:00
Mark Jessop 6dfa34cac8 Merge branch 'master' of github.com:projecthorus/horusdemodlib 2023-04-12 21:42:08 +09:30
Mark Jessop dd964915ca Add F1DZP 2023-04-12 21:41:57 +09:30
Mark Jessop 8dc2624d19
Merge pull request #145 from kng/docker
Docker implementation
2023-04-12 18:02:38 +09:30
Daniel Ekman a6f5ade965
Add workflow to build images, modify git/dockerignore
Signed-off-by: Daniel Ekman <knegge@gmail.com>
2023-04-12 09:30:37 +02:00
Daniel Ekman 1ffb9a9726 Add docker readme, update compose and env example 2023-04-11 17:49:26 +02:00
Mark Jessop 50a7d976b6 add YU7PDA 2023-03-31 22:25:39 +10:30
Mark Jessop e4f7a45d24 add PD2HSB 2023-03-25 07:46:35 +10:30
Mark Jessop 753eaadf66 Add YU4VMP and IKAR-1 2023-03-14 08:01:06 +10:30
Mark Jessop 1d573fde9b add F4HQO 2023-03-11 09:01:33 +10:30
Mark Jessop be5654ccea Add link to phi0 generator 2023-03-09 07:11:53 +10:30
Mark Jessop 020fdd9af2 Add ON3RC 2023-03-06 08:04:05 +10:30
Mark Jessop 642c5b8a53 Add DM7RM-2 2023-03-04 11:37:19 +10:30
Mark Jessop 7816115c63 add SP3WRO 2023-03-03 08:33:34 +10:30
Mark Jessop a59ce1d6ac add YU4BRE 2023-03-01 07:59:08 +10:30
Mark Jessop 566c498a7b add DO2LMV 2023-02-27 08:06:04 +10:30
Mark Jessop 61bb55bb12 add ALIEN-UFO-1 2023-02-25 20:43:08 +10:30
Mark Jessop c8c1a33677 Add KC1MOL 2023-02-24 16:17:42 +10:30
Mark Jessop 9e2cf89b03 Add 4 V2 IDs 2023-02-23 07:56:57 +10:30
Mark Jessop 187526e048 Add SpaceBoy 2023-02-21 09:47:38 +10:30
Mark Jessop 5cc986678e add DM7RM 2023-02-19 13:48:59 +10:30
Mark Jessop df7203635b Add VK2ARX 2023-02-15 19:12:46 +10:30
Mark Jessop 8bb7274dd4 More V2 IDs 2023-02-15 08:01:08 +10:30
Mark Jessop 8e910425fb More V2 IDs 2023-02-13 08:17:26 +10:30
Mark Jessop 1fc2bfbc90 add OK1OMG 2023-02-12 09:41:40 +10:30
Mark Jessop 1a06db585d Add WOHA-4FSK 2023-02-10 23:10:33 +10:30
Mark Jessop 65d285b3b5 add K6UCI 2023-02-10 08:12:42 +10:30
Mark Jessop 7717c04bb6 add M7ONS 2023-02-07 07:57:45 +10:30
Mark Jessop a2e4c1499a add DG2FS 2023-02-04 09:14:57 +10:30
Mark Jessop 13243eecfc AirSlicer C/D 2023-02-03 13:52:52 +10:30
Mark Jessop 485cb95aaf add YT1DRGTI 2023-02-02 17:13:17 +10:30
Mark Jessop 06e32fa6db add some V2 calls 2023-01-29 07:45:02 +10:30
Mark Jessop b37e006526 Add V2 id for W3YP 2023-01-26 09:01:40 +10:30
Mark Jessop 7e59d0871e Add custom fields for shsspgeiger 2023-01-16 19:44:14 +10:30
Mark Jessop e98f17eba9 Add 2 callsigns 2023-01-16 10:40:28 +10:30
Daniel Ekman 43ccf61661
Add rx_tools and soapysdr support
Signed-off-by: Daniel Ekman <knegge@gmail.com>
2023-01-14 13:13:50 +01:00
Daniel Ekman 90b95f81e1
Change to multistage builder and add run scripts
Signed-off-by: Daniel Ekman <knegge@gmail.com>
2023-01-12 21:22:18 +01:00
Daniel Ekman f526eb7cdc
Add docker compose and build
Signed-off-by: Daniel Ekman <knegge@gmail.com>
2023-01-12 13:46:45 +01:00
Mark Jessop 67f817e78d Add DF8AY 2023-01-11 19:03:18 +11:00
Mark Jessop 3d75b9803c Add YU1WAT-2 2023-01-11 08:57:39 +11:00
Mark Jessop 45049beb78 Add PD9BN-V2 2023-01-03 08:59:08 +10:30
Mark Jessop d52f214e08 add 2 V2 IDs 2022-12-31 10:33:06 +10:30
Mark Jessop c0498fa063
Merge pull request #115 from arkadiusz-papaj/master
Update payload_id_list.txt
2022-12-22 22:51:16 +10:30
Arek Papaj f985f22ea5
Update payload_id_list.txt
Assign ID 354 to SP9ARK-V2
2022-12-22 13:06:31 +01:00
Mark Jessop ad628782b6 Add V2 IDs 2022-12-22 09:08:11 +10:30
Mark Jessop a01931a57c Add 2 V2 IDs 2022-12-20 12:13:48 +10:30
Mark Jessop 50d7e18bed Disable habitat uploader, add warning when uploading 4FSKTEST telemetry 2022-12-18 17:14:22 +10:30
Mark Jessop b3a4537551 Add 2 new V2 IDs 2022-12-18 09:00:25 +10:30
Mark Jessop b5f0aeb3fd add 2 v2 ids 2022-12-09 08:50:52 +11:00
Mark Jessop 65f9073d5e
Merge pull request #114 from rohbot/master
Update payload_id_list.txt
2022-12-08 12:11:25 +11:00
Rohan Ahmad 2c6930a862
Update payload_id_list.txt
Adds MGGS-V2
2022-12-08 12:05:42 +11:00
Mark Jessop d246f1e302 Add F6ASP 2022-12-05 07:58:06 +11:00
Mark Jessop 7f46efb8fe Add 2 more V2 IDs 2022-11-29 10:11:43 +11:00
Mark Jessop 773c0c9d1b Add 2 V2 calls 2022-11-29 08:03:13 +11:00
Mark Jessop bedfab7aa2
Merge pull request #109 from piotr022/payload-id-sq9p
adding-sq9p
2022-11-28 06:48:55 +11:00
Piotr Lewandowski 9bd3a25250
adding-sq9p 2022-11-27 15:02:22 +01:00
Mark Jessop 434ef66459 Add YU1WAT 2022-11-26 10:11:19 +10:30
Mark Jessop 7e9866e735 Add YT3GTI 2022-11-24 18:39:54 +10:30
Mark Jessop bfcf935d75 Add KI5RQB 2022-11-17 16:13:03 +10:30
Mark Jessop 1ea53e7c2c Add PE1PSI v2 2022-11-13 09:38:32 +10:30
Mark Jessop 5270334ba5 Add horus geiger 2022-10-29 13:47:29 +10:30
Mark Jessop 924ea8a471 Add PD2SDV 2022-10-21 10:11:43 +10:30
Mark Jessop 92c01ce7c9 Add G7PMO-V2 2022-10-17 07:12:24 +10:30
Mark Jessop 8e8e5bc0a9 Add SP3POW-V2 2022-10-12 07:04:21 +10:30
Mark Jessop 5069789364 Add KB3ZOX/WOX 2022-10-10 07:15:52 +10:30
Mark Jessop 2abbed1f10 Modify SQ3KNL 2022-09-28 07:03:19 +09:30
Mark Jessop bc15d2e743 Add SQ3KNL 2022-09-27 21:24:59 +09:30
Mark Jessop fdf0a8d8f2 Added 2x ON callsigns 2022-09-27 08:08:48 +09:30
Mark Jessop 31ee507ec8 Add ON5RTR 2022-09-24 08:47:20 +09:30
Mark Jessop b89bf69abf Add SP6TKN-V2 2022-09-19 18:48:27 +09:30
Mark Jessop 84ad11e310 Send all custom fields via UDP broadcast, add baud rate and modulation details to sondehub uploader 2022-09-17 19:21:21 +09:30
Mark Jessop a377c0a2c2 Add some v2 IDs 2022-09-16 08:10:14 +09:30
Mark Jessop 7959544ca1
Merge pull request #101 from rohbot/master
Adds VK3PZ-V2 to payload_id
2022-09-14 17:10:17 +09:30
Rohan Ahmad de1b0ce130
Update payload_id_list.txt
adds VK3PZ-V2
2022-09-14 16:39:16 +10:00
Rohan Ahmad d70ab2475a
Update payload_id_list.txt
Adds  VK3PZ-HAB
2022-09-14 16:34:22 +10:00
Mark Jessop f1c9d1eea0 Add more ON4IR 2022-09-14 08:16:31 +09:30
Mark Jessop 11bd0386c8 Add SP3CET 2022-09-09 22:34:47 +09:30
Mark Jessop 10c53dd3d1 Added SP9ZHP 2022-09-09 07:19:23 +09:30
Mark Jessop ff0c378094 Add SP3VSS-V2 2022-09-06 06:44:12 +09:30
Mark Jessop 8c2f434b1a Add some v2 IDs 2022-09-04 06:39:36 +09:30
Mark Jessop 15ee6a549f Update horusradmon fioeld name 2022-09-02 15:41:52 +09:30
Mark Jessop 4310885959 Add Horus Radiation Monitior Payload 2022-09-02 15:22:46 +09:30
Mark Jessop afebdab448 add PH1M-V2 2022-08-29 20:22:12 +09:30
Mark Jessop dc66f63a5f Add some v1 IDs 2022-08-25 18:46:04 +09:30
Mark Jessop 34f38fa6c6 Add ON3PFD 2022-08-21 21:19:38 +09:30
Mark Jessop 1aa59feb31 Fix ON4IR custom field list 2022-08-16 07:11:15 +09:30
Mark Jessop 6defed3404 Add ON4IR custom field data 2022-08-14 15:53:53 +09:30
Mark Jessop 87cea7a206 Add ON4IR v2 ID 2022-08-14 08:44:03 +09:30
Mark Jessop 1e47384241 Add SQ9HP-V2 2022-08-13 10:30:06 +09:30
Mark Jessop 1cca89145a Add DJOAMF-V2 2022-08-11 18:50:46 +09:30
Mark Jessop a7709b1fca add 2 new v2 calls 2022-07-13 20:03:42 +09:30
Mark Jessop 2dcb15269d Add V2 ID for SN75ZOT-V2 2022-07-11 12:51:04 +09:30
Mark Jessop bee62eb29f OH3HAB alternate IDs 2022-07-02 20:38:51 +09:30
Mark Jessop f04ffad63b Add VK5ST-V2, Barossa 2022-07-01 18:07:08 +09:30
Mark Jessop 3ad81e0094 Handle EOF properly, handle no internet a bit better too 2022-06-26 10:32:53 +09:30
Mark Jessop ba24b76353 Add 2 new v1 ids 2022-06-25 14:30:15 +09:30
Mark Jessop 77a258070a OH3VHH to OH3HAB 2022-06-16 15:29:48 +09:30
Mark Jessop 2ccb69a675
Merge pull request #83 from rohbot/emdrc
Update payload_id_list.txt
2022-06-13 12:34:39 +09:30
Rohan Ahmad c102db80e4
Update payload_id_list.txt
adds EMDRC-V2 and VK3TRO-V2
2022-06-13 11:58:04 +10:00
Mark Jessop e5a75afb2c Add ICARO 2022-06-12 08:38:40 +09:30
Mark Jessop 6eefb2758f Add PE9GHZ-4FSK 2022-06-12 08:00:44 +09:30
Mark Jessop cc12c6493b Add SP3YDE-4FSK 2022-06-11 07:29:14 +09:30
Mark Jessop 44544c0724 Add Its windy 2022-06-03 17:22:45 +09:30
Mark Jessop ae9e12e220 Add SP3WRO 2022-05-24 18:07:22 +09:30
Mark Jessop 58a3bc54d0 Add SP6KZ-V2 2022-05-14 10:03:36 +09:30
Mark Jessop e3a386b2bb Reallocate ID 15 2022-05-04 18:24:49 +09:30
Mark Jessop 405d894be3 Rename KD2EAT, add W2CXM 2022-04-23 13:26:19 +09:30
Mark Jessop e2b597474a Add SQ7MHX 2022-04-21 08:08:45 +09:30
Mark Jessop a328cc7d11 more v1 ids 2022-04-20 19:54:03 +09:30
Mark Jessop ce76d2d6e1 Add 9A1FAB-4FSK 2022-04-20 08:06:25 +09:30
Mark Jessop 4492724b2e Add VK5ST-4FSK 2022-04-19 19:14:01 +09:30
Mark Jessop 88e3bcd845 Add PE1ANS-V2 2022-04-12 08:01:01 +09:30
Mark Jessop 41e297e4f1 Report modulation type 2022-04-10 11:34:22 +09:30
Mark Jessop 9f94677067 Reupload habitat listener data periodically 2022-04-10 10:54:24 +09:30
Mark Jessop 2628ded179 Add SP5RAF-4FSK 2022-04-03 11:09:06 +09:30
Mark Jessop 2faf80385f Add SP2SGF 2022-03-24 17:26:38 +10:30
Mark Jessop 56de7d6efd Add SQ6NEI-V2 2022-03-23 08:13:08 +10:30
Mark Jessop dbcea5bad5 add P 2022-03-17 07:55:32 +10:30
Mark Jessop 039834fdfb add SP6HD-V2 2022-03-15 07:16:08 +10:30
Mark Jessop 7935b6369a Add SP6V 2022-03-13 20:53:15 +10:30
Mark Jessop 3ac7be6614 V2 IDs 2022-03-10 17:41:01 +10:30
Mark Jessop 7b7e0cfaec Added some v2 IDs 2022-03-08 08:05:49 +10:30
Mark Jessop 3b89dbce1b add PA3EIV-4FSK 2022-03-08 08:02:24 +10:30
Mark Jessop 05a886ce76
Merge pull request #65 from MrARM/patch-1
Insert a payload V2 ID request
2022-03-08 07:35:19 +10:30
MrARM 733280497b
Insert a payload ID request 2022-03-07 11:19:52 -06:00
Mark Jessop d88f554937 Update after merge 2022-03-07 19:33:55 +10:30
Mark Jessop fec9b7c2c6 Add SP6TO 2022-03-07 19:32:34 +10:30
Mark Jessop 19342975a0
Merge pull request #63 from sq3tle/patch-1
Added payload_id
2022-03-05 00:56:16 +10:30
Filip Tomczyk 27f30d4f1d
Update payload_id_list.txt 2022-03-04 15:21:12 +01:00
Mark Jessop 19428b5e1e Add happysat 2022-03-04 16:22:21 +10:30
Mark Jessop 1ebdff2a79 Added 2 new v2 IDs 2022-03-03 17:18:27 +10:30
Mark Jessop 2f079df199 Add SP9DEV V2 IDs 2022-03-02 22:51:42 +10:30
Mark Jessop f63cd7e738 A few new payload IDs 2022-02-28 07:50:36 +10:30
Mark Jessop a08e977329 Add 2 new v2 IDs 2022-02-27 09:49:52 +10:30
Mark Jessop be24fcc006 Add PE2BZ-V2 2022-02-26 20:56:32 +10:30
Mark Jessop 939544e05d Update pyproj 2022-02-26 10:41:41 +10:30
Mark Jessop 32485a43f1 Fix uploading of custom fields to sondehub-amateur 2022-02-26 10:40:50 +10:30
Mark Jessop 3cef0956af Add a few new IDs, use 4FSKTEST-V2 custom fields by default 2022-02-20 18:50:37 +10:30
Mark Jessop fa8a0094ec Added 2 new calls 2022-02-19 09:27:43 +10:30
Mark Jessop 63ab639727 Added custom fields for HORUS-V2 2022-02-18 18:19:00 +10:30
Mark Jessop 66e519f2d6 Add sdrplusplus doc images 2022-02-18 15:45:28 +10:30
Mark Jessop 503614eb2c Add HORUS-V2 2022-02-17 21:12:34 +10:30
Mark Jessop 258497d5ef Add SQ1FYB 2022-02-17 16:48:00 +10:30
Mark Jessop 6881922e3b Add Flybag-4FSK 2022-02-13 10:31:22 +10:30
Mark Jessop 443bdd5727 Add some new V2 IDs 2022-02-12 15:10:52 +10:30
Mark Jessop 7f81e3b94b Add 9A4AM-V2 2022-02-11 21:38:15 +10:30
Mark Jessop 136ed393bd Add Peanut127 2022-02-09 17:30:57 +10:30
Mark Jessop e289ff7f1e add SP6SK-4FSK 2022-02-07 21:54:15 +10:30
Mark Jessop 15fa103b40 add SP6SK-4FSK 2022-02-07 21:53:45 +10:30
35 zmienionych plików z 1890 dodań i 100 usunięć

2
.dockerignore 100644
Wyświetl plik

@ -0,0 +1,2 @@
samples

59
.github/workflows/container.yml vendored 100644
Wyświetl plik

@ -0,0 +1,59 @@
name: Container Images
on:
push:
branches:
- 'testing'
tags:
- 'v*'
pull_request:
workflow_dispatch:
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Calculate Container Metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ghcr.io/${{ github.repository }}
- name: Setup QEMU
uses: docker/setup-qemu-action@v2
- name: Setup Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Images
if: ${{ github.event_name == 'pull_request' }}
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64, linux/386, linux/arm64, linux/arm/v6, linux/arm/v7
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build and Push Images
if: ${{ github.event_name != 'pull_request' }}
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64, linux/386, linux/arm64, linux/arm/v6, linux/arm/v7
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache
cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

12
.gitignore vendored
Wyświetl plik

@ -30,3 +30,15 @@
*.exe
*.out
*.app
# Custom config file
user.env
user.cfg
# IDE
.vscode
.idea
# cmake
build

53
Dockerfile 100644
Wyświetl plik

@ -0,0 +1,53 @@
FROM debian:bullseye as builder
MAINTAINER sa2kng <knegge@gmail.com>
RUN apt-get -y update && apt -y upgrade && apt-get -y install --no-install-recommends \
cmake \
build-essential \
ca-certificates \
git \
libusb-1.0-0-dev \
libatlas-base-dev \
libsoapysdr-dev \
soapysdr-module-all &&\
rm -rf /var/lib/apt/lists/*
# install everything in /target and it will go in to / on destination image. symlink make it easier for builds to find files installed by this.
RUN mkdir -p /target/usr && rm -rf /usr/local && ln -sf /target/usr /usr/local && mkdir /target/etc
COPY . /horusdemodlib
RUN cd /horusdemodlib &&\
cmake -B build -DCMAKE_INSTALL_PREFIX=/target/usr -DCMAKE_BUILD_TYPE=Release &&\
cmake --build build --target install
RUN git clone --depth 1 https://github.com/rxseger/rx_tools.git &&\
cd rx_tools &&\
cmake -B build -DCMAKE_INSTALL_PREFIX=/target/usr -DCMAKE_BUILD_TYPE=Release &&\
cmake --build build --target install
COPY scripts/* /target/usr/bin/
# to support arm wheels
RUN echo '[global]\nextra-index-url=https://www.piwheels.org/simple' > /target/etc/pip.conf
FROM debian:bullseye as prod
RUN apt-get -y update && apt -y upgrade && apt-get -y install --no-install-recommends \
libusb-1.0-0 \
python3-venv \
python3-crcmod \
python3-dateutil \
python3-numpy \
python3-requests \
python3-pip \
sox \
bc \
rtl-sdr \
libatlas3-base \
soapysdr-module-all &&\
rm -rf /var/lib/apt/lists/*
RUN pip install --system --no-cache-dir --prefer-binary horusdemodlib
COPY --from=builder /target /
CMD ["bash"]

114
README-Docker.md 100644
Wyświetl plik

@ -0,0 +1,114 @@
# Guide for running on docker
## Host system
This guide will assume an updated installation of Debian bullseye (11), it should work on a lot of different linux OS and architectures.<br>
You will need to install the libraries and supporting sw/fw for your sdr device, including udev rules and blacklists.<br>
Additional software such as soapysdr is not needed on the host, but can certainly be installed.<br>
```shell
sudo apt install rtl-sdr
echo "blacklist dvb_usb_rtl28xxu" | sudo tee /etc/modprobe.d/blacklist-rtlsdr.conf
sudo modprobe -r dvb_usb_rtl28xxu
```
See the [docker installation](#install-dockerio) at the bottom of this page.
## Building the image
If the docker image is not available, or you want to build from your own branch etc.
```shell
git clone https://github.com/projecthorus/horusdemodlib.git
cd horusdemodlib
docker-compose build
```
## Configuration
Start with creating a directory with a name representing the station, this will be shown in several places in the resulting stack.
```shell
mkdir -p projecthorus
cd projecthorus
wget https://raw.githubusercontent.com/projecthorus/horusdemodlib/master/docker-compose.yml
wget -O user.cfg https://raw.githubusercontent.com/projecthorus/horusdemodlib/master/user.cfg.example
wget -O user.env https://raw.githubusercontent.com/projecthorus/horusdemodlib/master/user.env.example
```
The file `user.env` contains all the station variables (earlier in each script), the DEMODSCRIPT is used by compose.<br>
The `user.cfg` sets the details sent to Sondehub.<br>
Use your favourite editor to configure these:
```shell
nano user.env
nano user.cfg
```
Please note that the values in user.env should not be escaped with quotes or ticks.
## Bringing the stack up
The `docker-compose` (on some systems it's `docker compose` without the hyphen) is the program controlling the creation, updating, building and termination of the stack.
The basic commands you will use is `docker-compose up` and `docker-compose down`.
When you edit the compose file or configuration it will try to figure out what needs to be done to bring the stack in sync of what has changed.
Starting the stack in foreground (terminate with Ctrl-C):
```shell
docker-compose up
```
Starting the stack in background:
```shell
docker-compose up -d
```
Stopping the stack:
```shell
docker-compose down
```
Updating the images and bringing the stack up:
```shell
docker-compose pull
docker-compose up -d
```
Over time there will be old images accumulating, these can be removed with `docker image prune -af`
## Using SoapySDR with rx_tools
If you want to use other SDR than rtl_sdr, the docker build includes rx_tools.<br>
Select docker_soapy_single.sh and add the extra argument to select the sdr in SDR_EXTRA:
```shell
# Script name
DEMODSCRIPT="docker_soapy_single.sh"
SDR_EXTRA="-d driver=rtlsdr"
```
## Monitoring and maintenance
Inside each container, the logs are output to stdout, which makes them visible from outside the container in the logs.
Starting to monitor the running stack:
```shell
docker-compose logs -f
```
If you want to run commands inside the containers, this can be done with the following command:
````shell
docker-compose exec horusdemod bash
````
The container needs to be running. Exit with Ctrl-D or typing `exit`.
# Install Docker.io
(Or you can install Docker.com engine via the [convenience script](https://docs.docker.com/engine/install/debian/#install-using-the-convenience-script))
In Debian bullseye there's already a docker package, so installation is easy:
```shell
sudo apt install docker.io apparmor
sudo apt -t bullseye-backports install docker-compose
sudo adduser $(whoami) docker
```
Re-login for the group permission to take effect.
The reason for using backports is the version of compose in bullseye is 1.25 and lacks cgroup support, the backport is version 1.27
<br>If your dist doesn't have backports, enable with this, and try the installation of docker-compose again:
```shell
echo "deb http://deb.debian.org/debian bullseye-backports main contrib non-free" | sudo tee /etc/apt/sources.list.d/backports.list
suod apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 648ACFD622F3D138 0E98404D386FA1D9
sudo apt update
```
If you cannot get a good compose version with your dist, please follow [the official guide](https://docs.docker.com/compose/install/linux/#install-the-plugin-manually).

Wyświetl plik

@ -65,7 +65,7 @@ A Python wrapper is also available (via the horusdemodlib Python library which i
## HorusDemodLib Python Library
The horusdemodlib Python library contains decoders for the different Project Horus telemetry formats, including:
* Horus Binary v1 (Legacy 22-byte Golay-encoded format)
* Horus Binary v2 (LDPC-Encoded 16 and 32-byte formats)
* Horus Binary v2 (Golay-encoded 32-byte format)
It also contains a wrapper around the C library (mentioned above), which contains the Horus modem demodulators.

Wyświetl plik

@ -19,13 +19,13 @@
]
},
"4FSKTEST-V2": {
"struct": "<BfBBH",
"comment": "Default custom fields for RS41ng",
"struct": "<hhBHxx",
"fields": [
["test_field 1", "none"],
["test_field 2", "none"],
["test_field 3", "battery_5v_byte"],
["test_field 4", "divide_by_10"],
["test_field 5", "divide_by_100"]
["ascent_rate", "divide_by_100"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"]
]
},
"MAGNU-V2": {
@ -37,5 +37,125 @@
["Travel", "divide_by_100"],
["Heading", "divide_by_100"]
]
},
"HORUS-V2": {
"struct": "<hhBHxx",
"fields": [
["ascent_rate", "divide_by_100"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"]
]
},
"VK5BRL-V2": {
"struct": "<hhBHxx",
"fields": [
["ascent_rate", "divide_by_100"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"]
]
},
"ON4IR": {
"comment": "ON4IR - UBA/IRM balloon custom fields",
"struct": "<hhBHH",
"fields": [
["ascent_rate", "divide_by_100"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"],
["pulse_counts","none"]
]
},
"HORUSRADMON": {
"comment": "Horus Radiation Monitor Payload, Photodiode",
"struct": "<hxxxxxH",
"fields": [
["ascent_rate", "divide_by_100"],
["pulse_counts","none"]
]
},
"HORUSGEIGER": {
"comment": "Horus Radiation Monitor Payload, Geiger Counter",
"struct": "<hxxxxxH",
"fields": [
["ascent_rate", "divide_by_100"],
["pulse_counts","none"]
]
},
"SHSSPGEIGER": {
"comment": "Horus Radiation Monitor Payload, Geiger Counter",
"struct": "<hxxxxxH",
"fields": [
["ascent_rate", "divide_by_100"],
["pulse_counts","none"]
]
},
"OH3HAB-4FSK-V2": {
"comment": "OH3HAB custom fields with RadSens and BME280 sensors",
"struct": "<HhBHH",
"fields": [
["radiation_intensity", "none"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"],
["pulse_counts","none"]
]
},
"AJ4XE": {
"comment": "custom fields for AJ4XE tracker",
"struct": "<HHBHH",
"fields": [
["HDOP", "divide_by_100"],
["VDOP", "divide_by_100"],
["TTF", "none"],
["PDOP", "divide_by_100"],
["AVG_SNR", "divide_by_100"]
]
},
"KD2EAT-DFM": {
"comment": "custom fields for KD2EAT DFM17 testing",
"struct": "<hhBHBx",
"fields": [
["ascent_rate", "divide_by_100"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"],
["mcu_calibration", "none"]
]
},
"DF7PN": {
"comment": "private values see https://github.com/whallmann/RS41HUP_V2",
"struct": "<HHxxxxx",
"fields": [
["flight_number", "none"],
["sonde_type", "none"]
]
},
"SP9SKP": {
"comment": "SKP telemetry",
"struct": "<BBBBBHH",
"fields": [
["fix_voltage", "battery_5v_byte"],
["io_voltage", "battery_5v_byte"],
["reset_voltage", "battery_5v_byte"],
["pv_voltage", "divide_by_100"],
["time_to_fix", "none"],
["uv_max", "none"],
["uv_avg", "none"]
]
},
"SKPQKM": {
"comment": "SKPQKM telemetry",
"struct": "<BBBBBHH",
"fields": [
["fix_voltage", "battery_5v_byte"],
["io_voltage", "battery_5v_byte"],
["reset_voltage", "battery_5v_byte"],
["pv_voltage", "divide_by_100"],
["time_to_fix", "none"],
["uv_max", "none"],
["uv_avg", "none"]
]
}
}
}

Wyświetl plik

@ -0,0 +1,178 @@
<mxfile host="app.diagrams.net" modified="2023-06-14T05:16:33.079Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36" etag="yB5OTHza8nv0mLeuWLmY" version="21.3.4" type="device">
<diagram name="Page-1" id="9Tq_Rg6amuM9MWHMLjdR">
<mxGraphModel dx="1022" dy="658" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="HftDXYYa0DBVADGEEzue-1" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;0&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="160" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-3" value="&lt;span style=&quot;font-size: 19px;&quot;&gt;8&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="200" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-4" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;16&lt;br&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-5" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Payload ID&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="160" y="160" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-7" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Frame No.&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="240" y="160" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-8" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;HH&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="320" y="160" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-9" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;MM&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="360" y="160" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-10" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;SS&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="400" y="160" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-11" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Lat&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="440" y="160" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-12" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Latitude&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="160" y="200" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-13" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Longitude&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
<mxGeometry x="280" y="200" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-14" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Alt&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="440" y="200" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-15" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Alt&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="160" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-16" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Vel.&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;" vertex="1" parent="1">
<mxGeometry x="200" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-17" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Sats&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad9d5;strokeColor=#ae4132;" vertex="1" parent="1">
<mxGeometry x="240" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-18" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Temp&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="280" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-19" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Batt&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
<mxGeometry x="320" y="240" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-20" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Custom&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d0cee2;strokeColor=#56517e;" vertex="1" parent="1">
<mxGeometry x="360" y="240" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-21" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Custom&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d0cee2;strokeColor=#56517e;" vertex="1" parent="1">
<mxGeometry x="160" y="280" width="240" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-22" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;CRC16&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#bac8d3;strokeColor=#23445d;" vertex="1" parent="1">
<mxGeometry x="400" y="280" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-23" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;24&lt;br&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="280" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-24" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;Byte&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;rotation=-90;" vertex="1" parent="1">
<mxGeometry x="20" y="220" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-25" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;0&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="400" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-26" value="&lt;span style=&quot;font-size: 19px;&quot;&gt;8&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="440" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-27" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;16&lt;br&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-28" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Payload ID&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="160" y="400" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-29" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Frame No.&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="240" y="400" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-30" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;HH&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="320" y="400" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-31" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;MM&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="360" y="400" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-32" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;SS&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="400" y="400" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-33" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Lat&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="440" y="400" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-34" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Latitude&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="160" y="440" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-35" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Longitude&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
<mxGeometry x="280" y="440" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-36" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Alt&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="440" y="440" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-37" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Alt&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="160" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-38" value="Vel-H" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad7ac;strokeColor=#b46504;" vertex="1" parent="1">
<mxGeometry x="200" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-39" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Sats&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fad9d5;strokeColor=#ae4132;" vertex="1" parent="1">
<mxGeometry x="240" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-40" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Temp&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b0e3e6;strokeColor=#0e8088;" vertex="1" parent="1">
<mxGeometry x="280" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-41" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Batt&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#b1ddf0;strokeColor=#10739e;" vertex="1" parent="1">
<mxGeometry x="320" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-42" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Ascent&lt;br&gt;Rate&lt;br&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d0cee2;strokeColor=#56517e;strokeWidth=2;dashed=1;" vertex="1" parent="1">
<mxGeometry x="360" y="480" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-44" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;CRC16&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#bac8d3;strokeColor=#23445d;" vertex="1" parent="1">
<mxGeometry x="400" y="520" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-45" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;24&lt;br&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="120" y="520" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-46" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;Byte&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;rotation=-90;" vertex="1" parent="1">
<mxGeometry x="20" y="460" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-47" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Ext.&lt;br&gt;Temp&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;dashed=1;" vertex="1" parent="1">
<mxGeometry x="440" y="480" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-50" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;Hum.&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;dashed=1;" vertex="1" parent="1">
<mxGeometry x="200" y="520" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-51" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;Pressure&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;strokeWidth=2;dashed=1;" vertex="1" parent="1">
<mxGeometry x="240" y="520" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-52" value="&lt;span style=&quot;font-size: 14px;&quot;&gt;Pulse &lt;br&gt;Count&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;strokeWidth=2;dashed=1;" vertex="1" parent="1">
<mxGeometry x="320" y="520" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-53" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;0&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="160" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-54" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;1&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="200" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-55" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;2&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="240" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-56" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;3&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="280" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-57" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;4&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="320" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-58" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;5&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="360" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-59" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;6&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="400" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-60" value="&lt;font style=&quot;font-size: 19px;&quot;&gt;7&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="440" y="360" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="HftDXYYa0DBVADGEEzue-61" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Ext.&lt;br&gt;Temp&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;dashed=1;" vertex="1" parent="1">
<mxGeometry x="160" y="520" width="40" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 180 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 48 KiB

21
docker-compose.yml 100644
Wyświetl plik

@ -0,0 +1,21 @@
version: '3.8'
services:
horusdemod:
build:
context: .
target: prod
image: 'ghcr.io/projecthorus/horusdemodlib:latest'
#read_only: true
device_cgroup_rules:
- 'c 189:* rwm'
env_file:
- './user.env'
command: 'bash -c $${DEMODSCRIPT}'
devices:
- '/dev/bus/usb'
volumes:
- type: 'tmpfs'
target: '/tmp'
- type: 'bind'
source: './user.cfg'
target: '/user.cfg'

Wyświetl plik

@ -1 +1 @@
__version__ = "0.3.2"
__version__ = "0.3.13"

Wyświetl plik

@ -50,6 +50,27 @@ def check_packet_crc(data:bytes, checksum:str='crc16'):
raise ValueError(f"Checksum - Unknown Checksym type {checksum}.")
def add_packet_crc(data:bytes, checksum:str='crc16'):
"""
Add a CRC onto the end of provided bytes
Support CRC types: CRC16-CCITT
"""
if (checksum == 'crc16') or (checksum == 'CRC16') or (checksum == 'crc16-ccitt') or (checksum == 'CRC16-CCITT'):
# Calculate a CRC over the data
_crc16 = crcmod.predefined.mkCrcFun('crc-ccitt-false')
_calculated_crc = _crc16(data)
_packet_crc = struct.pack('<H', _calculated_crc)
return data + _packet_crc
else:
raise ValueError(f"Checksum - Unknown Checksym type {checksum}.")
if __name__ == "__main__":

Wyświetl plik

@ -99,9 +99,17 @@ def decode_packet(data:bytes, packet_format:dict = None, ignore_crc:bool = False
'packet_format': packet_format,
'crc_ok': False,
'payload_id': 0,
'raw': codecs.encode(data, 'hex').decode().upper()
'raw': codecs.encode(data, 'hex').decode().upper(),
}
# Report the modulation type
if 'v1' in packet_format['name']:
_output['modulation'] = 'Horus Binary v1'
elif 'v2' in packet_format['name']:
_output['modulation'] = 'Horus Binary v2'
else:
_output['modulation'] = 'Horus Binary'
# Check the length provided in the packet format matches up with the length defined by the struct.
_struct_length = struct.calcsize(packet_format['struct'])
if _struct_length != packet_format['length']:
@ -138,15 +146,27 @@ def decode_packet(data:bytes, packet_format:dict = None, ignore_crc:bool = False
if _field_name == 'custom':
# Attempt to interpret custom fields.
# Note: This requires that the payload ID has been decoded prior to this field being parsed.
if _output['payload_id'] in horusdemodlib.payloads.HORUS_CUSTOM_FIELDS:
(_custom_data, _custom_str) = decode_custom_fields(_field_data, _output['payload_id'])
# If this payload has a specific custom field description, use that.
_custom_field_name = _output['payload_id']
else:
# Otherwise use the default from 4FSKTEST-V2, which matches
# the default fields from RS41ng
_custom_field_name = '4FSKTEST-V2'
(_custom_data, _custom_str) = decode_custom_fields(_field_data, _custom_field_name)
# Add custom fields to string
_ukhas_fields.append(_custom_str)
# Add custom fields to output dict.
for _field in _custom_data:
_output[_field] = _custom_data[_field]
_output['custom_field_names'] = list(_custom_data.keys())
# Add custom fields to string
_ukhas_fields.append(_custom_str)
# Add custom fields to output dict.
for _field in _custom_data:
_output[_field] = _custom_data[_field]
# Ignore checksum field. (and maybe other fields?)
elif _field_name not in ['checksum']:
@ -158,6 +178,11 @@ def decode_packet(data:bytes, packet_format:dict = None, ignore_crc:bool = False
_ukhas_fields.append(_decoded_str)
# Check the payload ID if > 256 for a Horus v2 packet.
if _output['modulation'] == 'Horus Binary v2':
if _raw_fields[0] < 256:
logging.warning("Found Payload ID < 256 in a Horus Binary v2 packet! This may lead to undefined behaviour. Please use a payload ID > 256!")
# Convert to a UKHAS-compliant string.
_ukhas_str = ",".join(_ukhas_fields)
_ukhas_crc = ukhas_crc(_ukhas_str.encode('ascii'))
@ -249,6 +274,7 @@ def parse_ukhas_string(sentence:str) -> dict:
# Produce a dict output which is compatible with the output of the binary decoder.
_telem = {
'raw': _raw,
'modulation': 'RTTY',
'callsign': _callsign,
'sequence_number': _sequence_number,
'time': _time,
@ -314,7 +340,9 @@ if __name__ == "__main__":
['horus_binary_v1', b'\x01\x12\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x1C\x9A\x95\x45', 'error'],
['horus_binary_v2_16byte', b'\x01\x12\x02\x00\x02\xbc\xeb!AR\x10\x00\xff\x00\xe1\x7e', ''],
# id seq_no HH MM SS lat lon alt spd sat tmp bat custom data -----------------------| crc16
['horus_binary_v2_32byte', b'\x00\x01\x02\x00\x0C\x22\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xB4\xC6', '']
['horus_binary_v2_32byte', b'\x00\x01\x02\x00\x0C\x22\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xB4\xC6', ''],
# id seq_no HH MM SS lat lon alt spd sat tmp bat custom data -----------------------| crc16
['horus_binary_v2_32byte_noident', b'\xff\xff\x02\x00\x0C\x22\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x17\x1c', '']
]
for _test in tests:

Wyświetl plik

@ -0,0 +1,269 @@
#!/usr/bin/env python3
#
# HorusDemodLib - Encoder helper functions
#
import ctypes
from ctypes import *
import codecs
import datetime
import logging
import sys
from enum import Enum
import os
import logging
from .decoder import decode_packet, hex_to_bytes
class Encoder():
"""
Horus Binary Encoder class.
Allows creation of a Horus Binary packet.
"""
def __init__(
self,
libpath=f"",
):
"""
Parameters
----------
libpath : str
Path to libhorus
"""
if sys.platform == "darwin":
libpath = os.path.join(libpath, "libhorus.dylib")
elif sys.platform == "win32":
libpath = os.path.join(libpath, "libhorus.dll")
else:
libpath = os.path.join(libpath, "libhorus.so")
# future improvement would be to try a few places / names
self.c_lib = ctypes.cdll.LoadLibrary(libpath)
# Encoder/decoder functions
self.c_lib.horus_l2_get_num_tx_data_bytes.restype = c_int
self.c_lib.horus_l2_encode_tx_packet.restype = c_int
# self.c_lib.horus_l2_encode_tx_packet.argtype = [
# POINTER(c_ubyte),
# c_ubyte *
# POINTER(c_ubyte),
# c_int
# ]
self.c_lib.horus_l2_decode_rx_packet.argtype = [
POINTER(c_ubyte),
POINTER(c_ubyte),
c_int
]
self.c_lib.horus_l2_gen_crc16.restype = c_ushort
self.c_lib.horus_l2_gen_crc16.argtype = [
POINTER(c_ubyte),
c_uint8
]
# Init
self.c_lib.horus_l2_init()
# in case someone wanted to use `with` style. I'm not sure if closing the modem does a lot.
def __enter__(self):
return self
def __exit__(self, *a):
self.close()
def close(self) -> None:
"""
Closes Horus modem. Does nothing here.
"""
pass
# Wrappers for libhorus C functions that we need.
def get_num_tx_data_bytes(self, packet_size) -> int:
"""
Calculate the number of transmit data bytes (uw+packet+fec) for a given
input packet size.
"""
return int(self.c_lib.horus_l2_get_num_tx_data_bytes(int(packet_size)))
def horus_l2_encode_packet(self, packet):
"""
Encode a packet using the Horus Binary FEC scheme, which:
- Generates Golay (23,12) FEC for the packet
- Adds this onto the packet contents, and interleaves/scrambles
- Adds a unique word (0x2424) to the start.
Packet input must be provided as bytes.
"""
if type(packet) != bytes:
raise TypeError("Input to encode_packet must be bytes!")
_unencoded = c_ubyte * len(packet)
_unencoded = _unencoded.from_buffer_copy(packet)
_num_encoded_bytes = self.get_num_tx_data_bytes(len(packet))
_encoded = c_ubyte * _num_encoded_bytes
_encoded = _encoded()
self.c_lib.horus_l2_encode_tx_packet.argtype = [
c_ubyte * _num_encoded_bytes,
c_ubyte * len(packet),
c_int
]
_num_bytes = int(self.c_lib.horus_l2_encode_tx_packet(_encoded, _unencoded, int(len(packet))))
return (bytes(_encoded), _num_bytes)
def horus_l2_decode_packet(self, packet, num_payload_bytes):
"""
Decode a Horus-Binary encoded data packet.
The packet must be provided as bytes, and must have the 2-byte unique word (0x2424)
at the start.
The expected number of output bytes must also be provided (22 or 32 for Horus v1 / v2 respectively)
"""
if type(packet) != bytes:
raise TypeError("Input to encode_packet must be bytes!")
_encoded = c_ubyte * len(packet)
_encoded = _encoded.from_buffer_copy(packet)
_decoded = c_ubyte * num_payload_bytes
_decoded = _decoded()
self.c_lib.horus_l2_encode_tx_packet.argtype = [
c_ubyte * num_payload_bytes,
c_ubyte * len(packet),
c_int
]
self.c_lib.horus_l2_decode_rx_packet(_decoded, _encoded, num_payload_bytes)
return bytes(_decoded)
def create_horus_v2_packet(self,
payload_id = 256,
sequence_number = 0,
time_dt = datetime.datetime.utcnow(),
latitude = 0.0,
longitude = 0.0,
altitude = 0.0,
speed = 0.0,
satellites = 0,
temperature = 0.0,
battery_voltage = 0.0,
# Default fields used for the 'custom' section of the packet.
ascent_rate = 0.0,
ext_temperature = 0.0,
ext_humidity = 0.0,
ext_pressure = 0.0,
# Alternate custom data - must be bytes, and length=9
custom_data = None
):
pass
# Sanity check input data.
if payload_id < 256 or payload_id > 65535:
raise ValueError("Invalid Horus v2 Payload ID. (Must be 256-65535)")
# Clip sequence number
sequence_number = int(sequence_number) % 65536
# Try and extract HHMMSS from time
try:
hours = int(time_dt.hour)
minutes = int(time_dt.minute)
seconds = int(time_dt.second)
except:
raise ValueError("Could not parse input datetime object.")
# Assume lat/lon are fine. They are just sent as floats anyway.
# Clip Altitude
altitude = int(altitude)
if altitude < 0:
altitude = 0
if altitude > 65535:
altitude = 65535
# Clip Speed (kph)
speed = int(speed)
if speed < 0:
speed = 0
if speed > 255:
speed = 255
# Clip sats
satellites = int(satellites)
if satellites < 0:
satellites = 0
if satellites > 255:
satellites = 255
# Temperature
# Battery voltage clip and conversion
# Custom data
# Ascent rate
# PTU data
# 'struct': '<HH3sffHBBbB9sH',
# 'checksum': 'crc16',
# 'fields': [
# ['payload_id', 'payload_id'],
# ['sequence_number', 'none'],
# ['time', 'time_hms'],
# ['latitude', 'degree_float'],
# ['longitude', 'degree_float'],
# ['altitude', 'none'],
# ['speed', 'none'],
# ['satellites', 'none'],
# ['temperature', 'none'],
# ['battery_voltage', 'battery_5v_byte'],
# ['custom', 'custom'],
# ['checksum', 'none']
# ]
if __name__ == "__main__":
import sys
e = Encoder()
# Check of get_num_tx_data_bytes
print(f"Horus v1: 22 bytes in, {e.get_num_tx_data_bytes(22)} bytes out.")
print(f"Horus v2: 32 bytes in, {e.get_num_tx_data_bytes(32)} bytes out.")
print("Encoder Tests: ")
horus_v1_unencoded = "000900071E2A000000000000000000000000259A6B14"
horus_v1_unencoded = "e701010000000000000000000000000000000022020000000000000000006e8e"
print(f" Horus v1 Input: {horus_v1_unencoded}")
horus_v1_unencoded_bytes = codecs.decode(horus_v1_unencoded, 'hex')
(_encoded, _num_bytes) = e.horus_l2_encode_packet(horus_v1_unencoded_bytes)
print(f" Horus v1 Output: {codecs.encode(_encoded, 'hex').decode().upper()}")
print("Decoder Tests:")
horus_v1_encoded = "2424C06B300D0415C5DBD332EFD7C190D7AF7F3C2891DE9F4BA1EB2B437BE1E2D8419D3DC9E44FDF78DAA07A98"
print(f" Horus v1 Input: {horus_v1_encoded}")
horus_v1_encoded_bytes = codecs.decode(horus_v1_encoded, 'hex')
_decoded = e.horus_l2_decode_packet(horus_v1_encoded_bytes, 22)
print(f" Horus v1 Output: {codecs.encode(_decoded, 'hex').decode().upper()}")

Wyświetl plik

@ -39,6 +39,7 @@ class HabitatUploader(object):
listener_lon=0.0,
listener_radio="",
listener_antenna="",
listener_upload_rate=3, # Hours
queue_size=64,
upload_timeout=10,
upload_retries=5,
@ -60,7 +61,22 @@ class HabitatUploader(object):
self.listener_lon = listener_lon
self.listener_radio = listener_radio
self.listener_antenna = listener_antenna
self.listener_upload_rate = listener_upload_rate
self.position_uploaded = False
self.last_listener_upload_time = 0
# Try and convert the supplied listener lat/lon to a float
# if this fails, just set the lat/lon to 0/0
try:
_lat = float(self.listener_lat)
_lon = float(self.listener_lon)
self.listener_lat = _lat
self.listener_lon = _lon
except:
logging.error("Could not parse listener lat/lon, setting both to 0.0")
self.listener_lat = 0.0
self.listener_lon = 0.0
self.last_freq_hz = None
@ -117,7 +133,7 @@ class HabitatUploader(object):
# Run the request.
try:
_req = requests.put(
_url, data=json.dumps(_data), timeout=self.upload_timeout
_url, data=json.dumps(_data), timeout=(self.upload_timeout, 6.1)
)
except Exception as e:
logging.error("Habitat - Upload Failed: %s" % str(e))
@ -175,29 +191,24 @@ class HabitatUploader(object):
# Wait for a short time before checking the queue again.
time.sleep(0.5)
if not self.position_uploaded:
# Validate the lat/lon entries.
try:
_lat = float(self.listener_lat)
_lon = float(self.listener_lon)
# Listener position upload
if (
time.time() - self.last_listener_upload_time
) > self.listener_upload_rate * 3600:
# Time to upload a listener postion
if (self.listener_lat != 0.0) or (self.listener_lon != 0.0):
_success = self.uploadListenerPosition(
self.user_callsign,
self.listener_lat,
self.listener_lon,
self.listener_radio,
self.listener_antenna,
)
if _success:
logging.info(f"Habitat - Listener information uploaded. Re-uploading in {self.listener_upload_rate} hours.")
if (_lat != 0.0) or (_lon != 0.0):
_success = self.uploadListenerPosition(
self.user_callsign,
_lat,
_lon,
self.listener_radio,
self.listener_antenna,
)
else:
logging.warning("Listener position set to 0.0/0.0 - not uploading.")
except Exception as e:
logging.error("Error uploading listener position: %s" % str(e))
# Set this flag regardless if the upload worked.
# The user can trigger a re-upload.
self.position_uploaded = True
# Update the last upload time.
self.last_listener_upload_time = time.time()
logging.info("Stopped Habitat Uploader Thread.")
@ -221,7 +232,7 @@ class HabitatUploader(object):
try:
self.habitat_upload_queue.put_nowait(sentence)
except Exception as e:
logging.error("Error adding sentence to queue: %s" % str(e))
logging.error("Habitat - Error adding sentence to queue, queue full.")
def close(self):
""" Shutdown uploader thread. """
@ -320,7 +331,6 @@ class HabitatUploader(object):
# post position to habitat
resp = self.postListenerData(doc)
if resp is True:
logging.info("Habitat - Listener information uploaded.")
return True
else:
logging.error("Habitat - Unable to upload listener information.")

Wyświetl plik

@ -53,6 +53,11 @@ def send_payload_summary(telemetry, port=55672, comment="HorusDemodLib"):
if 'speed' in telemetry:
packet['speed'] = telemetry['speed']
# Add in any field names from the custom field section
if "custom_field_names" in telemetry:
for _custom_field_name in telemetry["custom_field_names"]:
if _custom_field_name in telemetry:
packet[_custom_field_name] = telemetry[_custom_field_name]
# Set up our UDP socket
_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

Wyświetl plik

@ -7,7 +7,7 @@ import requests
import struct
# Global payload list - Basic version
HORUS_PAYLOAD_LIST = {0:'4FSKTEST', 1:'HORUSBINARY', 257:'4FSKTEST32', 65535:'HORUSTEST'}
HORUS_PAYLOAD_LIST = {0:'4FSKTEST', 1:'HORUSBINARY', 256: '4FSKTEST-V2'}
# URL for payload list
PAYLOAD_ID_LIST_URL = "https://raw.githubusercontent.com/projecthorus/horusdemodlib/master/payload_id_list.txt"
@ -35,18 +35,13 @@ HORUS_CUSTOM_FIELDS = {
]
},
"4FSKTEST-V2": {
"struct": "<BBBBBBBBB",
"struct": "<hhBHxx",
"fields": [
["test_field 1", "none"],
["test_field 2", "none"],
["test_field 3", "none"],
["test_field 4", "none"],
["test_field 5", "none"],
["test_field 6", "none"],
["test_field 7", "none"],
["test_field 8", "none"],
["test_field 9", "none"],
]
["ascent_rate", "divide_by_100"],
["ext_temperature", "divide_by_10"],
["ext_humidity", "none"],
["ext_pressure", "divide_by_10"]
]
}
}
@ -332,15 +327,20 @@ def update_payload_lists(payload_list, custom_field_list):
if __name__ == "__main__":
import argparse
# Setup Logging
logging.basicConfig(
format="%(asctime)s %(levelname)s: %(message)s", level=logging.DEBUG
)
# Read command-line arguments
parser = argparse.ArgumentParser(description="Test script for payload ID lists", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--download", action="store_false", default=True, help="Download lists from github, then check")
parser.add_argument("--print", action="store_true", default=False, help="Print content of payload ID lists")
args = parser.parse_args()
# Set up logging
logging.basicConfig(format="%(asctime)s %(levelname)s: %(message)s", level=logging.DEBUG)
init_payload_id_list()
print(HORUS_PAYLOAD_LIST)
init_payload_id_list(nodownload=args.download)
init_custom_field_list(nodownload=args.download)
init_custom_field_list()
print(HORUS_CUSTOM_FIELDS)
if args.print:
print(HORUS_PAYLOAD_LIST)
print(HORUS_CUSTOM_FIELDS)

Wyświetl plik

@ -155,6 +155,18 @@ class SondehubAmateurUploader(object):
# Datetime
try:
_datetime = fix_datetime(telemetry['time'])
# Compare system time and payload time, to look for issues where system time is way out.
_timedelta = abs((_datetime - datetime.datetime.utcnow()).total_seconds())
if _timedelta > 3*60:
# Greater than 3 minutes time difference. Discard packet in this case.
self.log_error("Payload and Receiver times are offset by more than 3 minutes. Either payload does not have GNSS lock, or your system time is not set correctly. Not uploading.")
return None
if _timedelta > 60:
self.log_warning("Payload and Receiver times are offset by more than 1 minute. Either payload does not have GNSS lock, or your system time is not set correctly.")
_output["datetime"] = _datetime.strftime(
"%Y-%m-%dT%H:%M:%S.%fZ"
)
@ -165,7 +177,16 @@ class SondehubAmateurUploader(object):
self.log_debug("Offending datetime_dt: %s" % str(telemetry["time"]))
return None
# Callsign
# Callsign - Break if this is an unknown payload ID.
if telemetry["callsign"] == "UNKNOWN_PAYLOAD_ID":
self.log_error("Not uploading telemetry from unknown payload ID. Is your payload ID list old?")
return None
if '4FSKTEST' in telemetry['callsign']:
self.log_warning(f"Payload ID {telemetry['callsign']} is for testing purposes only, and should not be used on an actual flight. Refer here: https://github.com/projecthorus/horusdemodlib/wiki#how-do-i-transmit-it")
_output['payload_callsign'] = telemetry["callsign"]
# Frame Number
@ -188,6 +209,15 @@ class SondehubAmateurUploader(object):
if telemetry["battery_voltage"] >= 0.0:
_output["batt"] = telemetry["battery_voltage"]
if "speed" in telemetry:
_output["speed"] = telemetry["speed"]
if "vel_h" in telemetry:
_output["vel_h"] = telemetry["vel_h"]
if "vel_v" in telemetry:
_output["vel_v"] = telemetry["vel_v"]
# Handle the additional SNR and frequency estimation if we have it
if "snr" in telemetry:
_output["snr"] = telemetry["snr"]
@ -198,6 +228,22 @@ class SondehubAmateurUploader(object):
if "raw" in telemetry:
_output["raw"] = telemetry["raw"]
if "modulation" in telemetry:
_output["modulation"] = telemetry["modulation"]
if "modulation_detail" in telemetry:
_output["modulation_detail"] = telemetry["modulation_detail"]
if "baud_rate" in telemetry:
_output["baud_rate"] = telemetry["baud_rate"]
# Add in any field names from the custom field section
if "custom_field_names" in telemetry:
for _custom_field_name in telemetry["custom_field_names"]:
if _custom_field_name in telemetry:
_output[_custom_field_name] = telemetry[_custom_field_name]
logging.debug(f"Sondehub Amateur Uploader - Generated Packet: {str(_output)}")
return _output
@ -298,7 +344,31 @@ class SondehubAmateurUploader(object):
_upload_success = True
break
elif _req.status_code == 500:
elif _req.status_code == 202:
# A 202 return code means there was some kind of data issue.
# We expect a response of the form {"message": "error message", "errors":[], "warnings":[]}
try:
_resp_json = _req.json()
for _error in _resp_json['errors']:
self.log_error("Payload data error: " + _error["error_message"])
if 'payload' in _error:
self.log_debug("Payload data associated with error: " + str(_error['payload']))
for _warning in _resp_json['warnings']:
self.log_warning("Payload data warning: " + _warning["warning_message"])
if 'payload' in _warning:
self.log_debug("Payload data associated with warning: " + str(_warning['payload']))
except Exception as e:
self.log_error("Error when parsing 202 response: %s" % str(e))
self.log_debug("Content of 202 response: %s" % _req.text)
_upload_success = True
break
elif _req.status_code in [500,501,502,503,504]:
# Server Error, Retry.
_retries += 1
continue
@ -358,7 +428,8 @@ class SondehubAmateurUploader(object):
headers=headers,
)
except Exception as e:
self.log_error("Upload Failed: %s" % str(e))
self.log_error("Station position upload failed: %s" % str(e))
self.last_user_position_upload = time.time()
return
if _req.status_code == 200:
@ -427,6 +498,13 @@ class SondehubAmateurUploader(object):
"""
logging.error("Sondehub Amateur Uploader - %s" % line)
def log_warning(self, line):
""" Helper function to log a warning message with a descriptive heading.
Args:
line (str): Message to be logged.
"""
logging.warning("Sondehub Amateur Uploader - %s" % line)
if __name__ == "__main__":
# Test Script

Wyświetl plik

@ -72,6 +72,7 @@ def main():
# parser.add_argument("--summary", type=int, default=-1, help="Override user.cfg UDP Summary output port. (NOT IMPLEMENTED)")
parser.add_argument("--freq_hz", type=float, default=None, help="Receiver IQ centre frequency in Hz, used in determine the absolute frequency of a telemetry burst.")
parser.add_argument("--freq_target_hz", type=float, default=None, help="Receiver 'target' frequency in Hz, used to add metadata to station position info.")
parser.add_argument("--baud_rate", type=int, default=None, help="Modulation baud rate (Hz), used to add additional metadata info.")
parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose output (set logging level to DEBUG)")
args = parser.parse_args()
@ -97,6 +98,9 @@ def main():
else:
_logfile = None
# Some variables to handle re-downloading of payload ID lists.
min_download_time = 30*60 # Only try and download new payload ID / custom field lists every 30 min.
next_download_time = time.time()
if args.rtty == False:
@ -105,7 +109,7 @@ def main():
horusdemodlib.payloads.HORUS_PAYLOAD_LIST = read_payload_list(filename=args.payload_list)
horusdemodlib.payloads.HORUS_CUSTOM_FIELDS = read_custom_field_list(filename=args.custom_fields)
else:
# Downlaod
# Download
horusdemodlib.payloads.HORUS_PAYLOAD_LIST = init_payload_id_list(filename=args.payload_list)
horusdemodlib.payloads.HORUS_CUSTOM_FIELDS = init_custom_field_list(filename=args.custom_fields)
@ -120,15 +124,6 @@ def main():
else:
_listener_freq_str = ""
habitat_uploader = HabitatUploader(
user_callsign = user_config['user_call'],
listener_lat = user_config['station_lat'],
listener_lon = user_config['station_lon'],
listener_radio = user_config['radio_comment'] + _listener_freq_str,
listener_antenna = user_config['antenna_comment'],
inhibit=args.noupload
)
if user_config['station_lat'] == 0.0 and user_config['station_lon'] == 0.0:
_sondehub_user_pos = None
else:
@ -138,7 +133,7 @@ def main():
upload_rate = 2,
user_callsign = user_config['user_call'],
user_position = _sondehub_user_pos,
user_radio = user_config['radio_comment'],
user_radio = user_config['radio_comment'] + _listener_freq_str,
user_antenna = user_config['antenna_comment'],
software_name = "horusdemodlib",
software_version = horusdemodlib.__version__,
@ -158,7 +153,7 @@ def main():
if (data == ''):
# Empty line means stdin has been closed.
logging.info("Caught EOF, exiting.")
logging.critical("Caught EOF (rtl_fm / horus_demod processes have exited, maybe because there's no RTLSDR?), exiting.")
break
# Otherwise, strip any newlines, and continue.
@ -182,14 +177,18 @@ def main():
# Add in frequency estimate, if we have been supplied a receiver frequency.
if args.freq_hz:
_decoded['f_centre'] = int(demod_stats.fest_mean) + int(args.freq_hz)
habitat_uploader.last_freq_hz = _decoded['f_centre']
#habitat_uploader.last_freq_hz = _decoded['f_centre']
# Add in baud rate, if provided.
if args.baud_rate:
_decoded['baud_rate'] = int(args.baud_rate)
# Send via UDP
send_payload_summary(_decoded, port=user_config['summary_port'])
# Upload the string to Habitat
_decoded_str = "$$" + data.split('$')[-1] + '\n'
habitat_uploader.add(_decoded_str)
#_decoded_str = "$$" + data.split('$')[-1] + '\n'
#habitat_uploader.add(_decoded_str)
# Upload the string to Sondehub Amateur
sondehub_uploader.add(_decoded)
@ -219,6 +218,23 @@ def main():
try:
_decoded = decode_packet(_binary_string)
# If we get here, we have a valid packet!
if (_decoded['callsign'] == "UNKNOWN_PAYLOAD_ID") and not args.nodownload:
# We haven't seen this payload ID. Our payload ID list might be out of date.
if time.time() > next_download_time:
logging.info("Observed unknown Payload ID, attempting to re-download lists.")
# Download lists.
horusdemodlib.payloads.HORUS_PAYLOAD_LIST = init_payload_id_list(filename=args.payload_list)
horusdemodlib.payloads.HORUS_CUSTOM_FIELDS = init_custom_field_list(filename=args.custom_fields)
# Update next_download_time so we don't re-attempt to download with every new packet.
next_download_time = time.time() + min_download_time
# Re-attempt to decode the packet.
_decoded = decode_packet(_binary_string)
if _decoded['callsign'] != "UNKNOWN_PAYLOAD_ID":
logging.info(f"Payload found in new payload ID list - {_decoded['callsign']}")
# Add in SNR data.
_snr = demod_stats.snr
@ -227,13 +243,17 @@ def main():
# Add in frequency estimate, if we have been supplied a receiver frequency.
if args.freq_hz:
_decoded['f_centre'] = int(demod_stats.fest_mean) + int(args.freq_hz)
habitat_uploader.last_freq_hz = _decoded['f_centre']
#habitat_uploader.last_freq_hz = _decoded['f_centre']
# Add in baud rate, if provided.
if args.baud_rate:
_decoded['baud_rate'] = int(args.baud_rate)
# Send via UDP
send_payload_summary(_decoded, port=user_config['summary_port'])
# Upload to Habitat
habitat_uploader.add(_decoded['ukhas_str']+'\n')
# Do not upload Horus Binary packets to the Habitat endpoint.
# habitat_uploader.add(_decoded['ukhas_str']+'\n')
# Upload the string to Sondehub Amateur
sondehub_uploader.add(_decoded)
@ -243,13 +263,19 @@ def main():
_logfile.flush()
logging.info(f"Decoded Binary Packet (SNR {demod_stats.snr:.1f} dB): {_decoded['ukhas_str']}")
# Remove a few fields from the packet before printing.
_temp_packet = _decoded.copy()
_temp_packet.pop('packet_format')
_temp_packet.pop('ukhas_str')
logging.debug(f"Binary Packet Contents: {_temp_packet}")
except Exception as e:
logging.error(f"Decode Failed: {str(e)}")
except KeyboardInterrupt:
logging.info("Caught CTRL-C, exiting.")
habitat_uploader.close()
#habitat_uploader.close()
sondehub_uploader.close()
if __name__ == "__main__":
main()

Wyświetl plik

@ -22,7 +22,7 @@
12, DK0WT-4FSK
13, PE1ANS-4FSK
14, WBLSCOUTS-4FSK
15, PB0AHX-4FSK
15, PA0CAB-4FSK
16, PRESCOTTSOUTH
17, EAGLE-1-4FSK
18, VK8TH-4FSK
@ -48,7 +48,7 @@
38, DH3SUP-4FSK
39, LUX2
40, SP5YAM-4FSK
41, PD5MF-4FSK
41, PA5MF-4FSK
42, SQ3XBD-4FSK
43, SP6QKM-4FSK
44, SQ6RQT-4FSK
@ -63,7 +63,7 @@
53, SP3MCY-4FSK
54, VK3TRO-4FSK
55, SP3QDX-4FSK
56, SP10POW-4FSK
56, SP3POW-4FSK
57, SP8ESA-4FSK
58, 9A4AM-4FSK
59, 9A3ZI-4FSK
@ -73,9 +73,9 @@
63, SP6VWX-4FSK
64, SV3IRG-4FSK
65, LUX3
66, OH3VHH-4FSK
66, OH3HAB-4FSK
67, SQ3KNL-4FSK
68, PE1PSI-4FSK
68, Flybag-2
69, SP6KZ-4FSK
70, LY2BAW-4FSK
71, SQ2DEF-4FSK
@ -94,14 +94,377 @@
84, SP9DEV-4FSK
85, 9A4VS-4FSK
86, WD6DRI
87, KD2EAT
87, KD2EAT-4FSK
88, SQ3KNO-4FSK
89, SP6ZHP-4FSK
90, UPANDUP
91, 9A6NDZ-4FSK
92, DG8JT-4FSK
93, SP6HD-4FSK
94, SP6SK-4FSK
95, Peanut127
96, Flybag-4FSK
97, SQ1FYB-4FSK
98, W3YP
99, KN6SPE
100, SQ3MP-4FSK
101, KN6SNE
102, KN6SNF
103, SQ3TLE
104, SP6TO
105, PA3EIV-4FSK
106, SP6V-4FSK
107, PD7R-4FSK
108, SP2SGF-4FSK
109, SP5RAF-4FSK
110, VK5ST-4FSK
111, 9A1FAB-4FSK
112, 9A1GIJ-4FSK
113, 9A9Y-4FSK
114, SQ7MHX-4FSK
115, W2CXM-4FSK
116, SP3WRO-4FSK
117, SP3YDE-4FSK
118, PE9GHZ-4FSK
119, ICARO
120, SP3GTP-4FSK
121, SP3LM-4FSK
122, SQ6ODL-4FSK
123, HF8FRN-4FSK
124, SP3CET-4FSK
# IDs for 32-byte payloads
256, 4FSKTEST-V2
257, OH3VHH-4FSK-V2
257, OH3HAB-4FSK-V2
258, MAGNU-V2
259, 9A4AM-V2
260, Peanut127-V2
261, 9A3ZI-V2
262, SQ1FYB-V2
263, SQ3MP-V2
264, VK5BRL-V2
265, PE2BZ-V2
266, SQ9GIN-V2
267, HF9ZHP-V2
268, SP9DEV-1-V2
269, SP9DEV-2-V2
270, SP9DEV-3-V2
271, W6SUN-V2
272, WD6DRI-V2
273, HAPPYSAT-V2
274, SQ3TLE-8-V2
275, SQ3TLE-9-V2
276, SQ3TLE-10-V2
277, SP6TO-V2
278, N0UUU-V2
279, SP6ZWR-V2
280, SP6QKM-V2
281, SQ6RQT-V2
282, SQ6NLN-V2
283, SP6ZHP-V2
284, SQ6ODL-V2
285, KQ6RS-V2
286, KA9Q-V2
287, KN6SPE-V2
288, KN6SNE-V2
289, KN6SNF-V2
290, WB9COY-V2
291, SP6V-V2
292, SP6HD-V2
293, PD7R-V2
294, SQ6NEI-V2
295, SP2SGF-V2
296, PE1ANS-V2
297, SQ7MHX-V2
298, SP6KZ-V2
299, VK3TRO-V2
300, EMDRC-V2
301, VK5ST-V2
302, BAROSSA
303, OH3HAB-2-4FSK-V2
304, OH3HAB-3-4FSK-V2
305, SN75ZOT-V2
306, PD5A-4FSK
307, PA3DJR-4FSK
308, DJOAMF-V2
309, SQ9HP-V2
310, ON4IR
311, ON3PFD
312, PH1M-V2
313, PSC1-4FSK
314, KK6NOW
315, SP3VSS-V2
316, SP9ZHP-V2
317, SP3CET-V2
318, ON4IR-1
319, ON4IR-2
320, ON4IR-3
321, ON4IR-4
322, VK3PZ-V2
323, DK7SCH
324, PA3CPF-V2
325, SP6TKN-V2
326, ON5RTR
327, ON4BCY
328, ON2KGC
329, SQ3KNL-V2
330, KB3ZOX
331, KB3ZOW
332, SP3POW-V2
333, G7PMO-V2
334, PD2SDV
335, PE1PSI
336, KI5RQB
337, YT3GTI-V2
338, YU1WAT
339, SQ9P-4FSK
340, 9A6NDZ
341, 9A4VS
342, F5MVO
343, F5RZC
344, F6ASP
345, MGGS-V2
346, KI6ZUM
347, KJ6KDZ
348, DO2JMG
349, BIOWL1
350, AirSlicer-A
351, AirSlicer-B
352, DG0CCO
353, SHSSP2023
354, SP9ARK-V2
355, ON2ON-V2
356, CHEFERIK
357, PD9BN-V2
358, YU1WAT-2
359, DF8AY
360, SHSSPGEIGER
361, VK2ZTH
362, W3YP
363, SP3BTT
364, SP3OEY
365, SP3QFO
366, SQ3GOS
367, YT1DRGTI
368, AirSlicer-C
369, AirSlicer-D
370, DG2FS
371, M7ONS
372, K6UCI
373, WOHA-4FSK
374, OK1OMG
375, OK1GAL
376, OK1MDX
377, OK1MDR
378, F6KMF
379, PD3EGE
380, W0MXX
381, VK2ARX
382, Altostratus
383, SpaceBoy
384, F5APQ
385, F4HRD
386, F1OIL
387, SQ3RAX
388, KC1MOL
389, ALIEN-UFO-1
390, DO2LMV
391, YU4BRE
392, SP3WRO
393, DM7RM-2
394, ON3RC
395, F4HQO
396, YU4VMP
397, IKAR-1
398, PD2HSB
399, YU7PDA
400, F1DZP
401, SP6ONZ
402, OH3CUF
403, W3YP-2
404, IW1DBF
405, SP7AR
406, VK3DNS-JMSS
407, HA8LOU
408, DM2DL
409, W1STR
410, WS-RS1
411, WS-RS2
412, FHS-RS1
413, SP3ABS-V2
414, SP5LOT
415, 9A7DI
416, SQ5RB
417, KD2EAT
418, W2CXM
419, OM2OFA-1
420, OM2OFA-2
421, OM2OFA-3
422, OM2OFA-4
423, OM2OFA-5
424, OM2OFA-6
425, DO5IO
426, SP5GFN
427, PA5MF
428, KN6ZTT
429, SP3ZHP
430, HG8LXL
431, SQ3XBD
432, SOLflight
433, W1U
434, MONASAT
435, SP3ET-2
436, SNSF01
437, DJ9AS
438, F8DKG
439, SP5WWL
440, SP5YAM
441, KB4RKS
442, O38
443, SOLARBAG
444, DL1MRZ-1
445, DL1MRZ-2
446, DL1MRZ-3
447, DL1MRZ-4
448, KI5RZY
449, PA0CAB
450, DL6PI
451, PA3GPU-GSN-4FSK
452, FUN-4FSK
453, KE2BOK
454, SP4CE
455, FLIGHTDESIGN
456, FLIGHTDESIGN2
457, KM6OIR
458, M7NGO
459, DK0WT-V2
460, PD2JM
461, DB7XO
462, FEMTO
463, OH7FES
464, K4KDR
465, 2E0NNF
466, OK1RAJ
467, COSMO-PK
468, FlightKW
469, AJ4XE
470, WJ2B
471, BINAR
472, SKYSITE
473, KO6BXV
474, KO6BZF
475, KO6CAP
476, KO6BZU
477, KO6BYH
478, KO6BZW
479, KO6BZV
480, KO6CAM
481, KO6CAN
482, KO6CAO
483, KO6CAC
484, KO6BZN
485, KG6EQU
486, DF7PN
487, WOHA-SOLAR
488, F5IKO
489, DJ2DS
490, DS-11
491, DO2LYB
492, Stratonaut
493, DK7TD
494, DC1NSK
495, DL2ALY
496, StratoSack
497, SP9SKP
498, SP6ZWR
499, SP3RST
500, SP2ROC
501, KD2EAT-DFM
502, SN32WOSP
503, KA7NSR
504, Lyoner
505, G8FJG
506, IW1DBF
507, ICARO
508, DEDALO
509, DL1XH
510, F4EHY
511, IU0MUN
512, IZ0CGP
513, VK3FUR
514, RXSONDE
515, Molly-1
516, IT9EWK
517, NEC_CQ73
518, YT1C
519, 9A4GE
520, PE9M
521, PD3T
522, PE1GLG
523, KITE-1
524, 9A1FER
525, SP6QKM
526, SP8KDE
527, SQ8AOL
528, SQ9AOL
529, NANO-1
530, SKPQKM
531, DG4CG
532, KJ0RE
533, PA4VB
534, PA4VB-KITE
535, F6AGV-BHAF
536, KE2CBS
537, PA3EIV
538, PA9K
539, YU7TDA
540, 9A4GE-2
541, F1AQE
542, PD1EG
543, Xpico
544, SP7XSS
545, SP7XSS-2
546, SP9RKF
547, KB3ZOX-2
548, 9A3SWO
549, KD2KPZ
550, F4KLR
551, PD1NW
552, PA3ADE-KITE
553, SQ6DAG
554, StratoSoar
555, DG4CG-2
556, DG4CG-3
557, DG4CG-1
558, AK3F
559, Martinus-MZ
560, DG4CG-4
561, DG4CG-5
562, DG4CG-6
563, SQ2CPA
564, Party-Time
565, PWrSpace-in
566, RFA-0
567, RFA-1
568, RFA-2
569, 9A4GE-3
570, MATHRO
571, RUEDGUE
572, IDA
573, DL9GKJ
574, PA0ESH
575, Ypico
576, SP9WAK
577, DG4CG-Solar
578, DB1TH
579, DL1BRF
580, PD7BOR
581, PA0CAB-lastflight
582, SQ2CPA-31
583, SQ2CPA-32
584, SQ2CPA-33
31415, HORUS-V2
31416, ITSWINDY
31417, HORUSRADMON
31418, HORUSGEIGER
31419, VI25AREG
31420, VK5ARG

Wyświetl plik

@ -1,6 +1,6 @@
[tool.poetry]
name = "horusdemodlib"
version = "0.3.2"
version = "0.3.13"
description = "Project Horus HAB Telemetry Demodulators"
authors = ["Mark Jessop"]
license = "LGPL-2.1-or-later"

Wyświetl plik

@ -0,0 +1,50 @@
#!/usr/bin/env bash
#
# Dual Horus Binary Decoder Script
# Intended for use with Dual Launches, where both launches have 4FSK payloads closely spaced (~10 kHz)
#
# The SDR is tuned 5 kHz below the Lower 4FSK frequency, and the frequency estimators are set across the two frequencies.
# Modem statistics are sent out via a new 'MODEM_STATS' UDP broadcast message every second.
#
# Calculate the frequency estimator limits
# Note - these are somewhat hard-coded for this dual-RX application.
MFSK1_LOWER=$(echo "$MFSK1_SIGNAL - $RXBANDWIDTH/2" | bc)
MFSK1_UPPER=$(echo "$MFSK1_SIGNAL + $RXBANDWIDTH/2" | bc)
MFSK1_CENTRE=$(echo "$RXFREQ + $MFSK1_SIGNAL" | bc)
MFSK2_LOWER=$(echo "$MFSK2_SIGNAL - $RXBANDWIDTH/2" | bc)
MFSK2_UPPER=$(echo "$MFSK2_SIGNAL + $RXBANDWIDTH/2" | bc)
MFSK2_CENTRE=$(echo "$RXFREQ + $MFSK2_SIGNAL" | bc)
echo "Using SDR Centre Frequency: $RXFREQ Hz."
echo "Using MFSK1 estimation range: $MFSK1_LOWER - $MFSK1_UPPER Hz"
echo "Using MFSK2 estimation range: $MFSK2_LOWER - $MFSK2_UPPER Hz"
BIAS_SETTING=""
if [ "$BIAS" = "1" ]; then
echo "Enabling Bias Tee."
BIAS_SETTING=" -T"
fi
GAIN_SETTING=""
if [ "$GAIN" = "0" ]; then
echo "Using AGC."
GAIN_SETTING=""
else
echo "Using Manual Gain"
GAIN_SETTING=" -g $GAIN"
fi
STATS_SETTING=""
if [ "$STATS_OUTPUT" = "1" ]; then
echo "Enabling Modem Statistics."
STATS_SETTING=" --stats=100"
fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($RXFREQ) and 'target' signal frequency ($MFSK1_CENTRE)
# to enable providing additional metadata to Habitat / Sondehub.
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ | tee >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK1_LOWER --fsk_upper=$MFSK1_UPPER - - | python3 -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK1_CENTRE ) >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK2_LOWER --fsk_upper=$MFSK2_UPPER - - | python3 -m horusdemodlib.uploader --freq_hz $RXFREQ ) > /dev/null

Wyświetl plik

@ -0,0 +1,52 @@
#!/usr/bin/env bash
#
# Dual RTTY / Horus Binary Decoder Script
# Intended for use on Horus flights, with the following payload frequencies:
# RTTY: 434.650 MHz - Callsign 'HORUS'
# MFSK: 434.660 MHz - Callsign 'HORUSBINARY'
#
# The SDR is tuned 5 kHz below the RTTY frequency, and the frequency estimators are set across the two frequencies.
# Modem statistics are sent out via a new 'MODEM_STATS' UDP broadcast message every second.
#
# Calculate the frequency estimator limits
# Note - these are somewhat hard-coded for this dual-RX application.
RTTY_LOWER=$(echo "$RTTY_SIGNAL - $RXBANDWIDTH/2" | bc)
RTTY_UPPER=$(echo "$RTTY_SIGNAL + $RXBANDWIDTH/2" | bc)
RTTY_CENTRE=$(echo "$RXFREQ + $RTTY_SIGNAL" | bc)
MFSK_LOWER=$(echo "$MFSK_SIGNAL - $RXBANDWIDTH/2" | bc)
MFSK_UPPER=$(echo "$MFSK_SIGNAL + $RXBANDWIDTH/2" | bc)
MFSK_CENTRE=$(echo "$RXFREQ + $MFSK_SIGNAL" | bc)
echo "Using SDR Centre Frequency: $RXFREQ Hz."
echo "Using RTTY estimation range: $RTTY_LOWER - $RTTY_UPPER Hz"
echo "Using MFSK estimation range: $MFSK_LOWER - $MFSK_UPPER Hz"
BIAS_SETTING=""
if [ "$BIAS" = "1" ]; then
echo "Enabling Bias Tee."
BIAS_SETTING=" -T"
fi
GAIN_SETTING=""
if [ "$GAIN" = "0" ]; then
echo "Using AGC."
GAIN_SETTING=""
else
echo "Using Manual Gain"
GAIN_SETTING=" -g $GAIN"
fi
STATS_SETTING=""
if [ "$STATS_OUTPUT" = "1" ]; then
echo "Enabling Modem Statistics."
STATS_SETTING=" --stats=100"
fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($RXFREQ) and 'target' signal frequency ($RTTY_CENTRE / $MFSK_CENTRE)
# to enable providing additional metadata to Habitat / Sondehub.
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ | tee >($DECODER -q --stats=5 -g -m RTTY --fsk_lower=$RTTY_LOWER --fsk_upper=$RTTY_UPPER - - | python3 -m horusdemodlib.uploader --rtty --freq_hz $RXFREQ --freq_target_hz $RTTY_CENTRE ) >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK_LOWER --fsk_upper=$MFSK_UPPER - - | python3 -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK_CENTRE ) > /dev/null

Wyświetl plik

@ -0,0 +1,37 @@
#!/usr/bin/env bash
#
# Horus Binary RTLSDR Helper Script
#
# Uses rtl_fm to receive a chunk of spectrum, and passes it into horus_demod.
#
# Calculate the SDR tuning frequency
SDR_RX_FREQ=$(echo "$RXFREQ - $RXBANDWIDTH/2 - 1000" | bc)
# Calculate the frequency estimator limits
FSK_LOWER=1000
FSK_UPPER=$(echo "$FSK_LOWER + $RXBANDWIDTH" | bc)
echo "Using SDR Centre Frequency: $SDR_RX_FREQ Hz."
echo "Using FSK estimation range: $FSK_LOWER - $FSK_UPPER Hz"
BIAS_SETTING=""
if [ "$BIAS" = "1" ]; then
echo "Enabling Bias Tee."
BIAS_SETTING=" -T"
fi
GAIN_SETTING=""
if [ "$GAIN" = "0" ]; then
echo "Using AGC."
GAIN_SETTING=""
else
echo "Using Manual Gain"
GAIN_SETTING=" -g $GAIN"
fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($SDR_RX_FREQ) and 'target' signal frequency ($RXFREQ)
# to enable providing additional metadata to Habitat / Sondehub.
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $SDR_RX_FREQ | $DECODER -q --stats=5 -g -m binary --fsk_lower=$FSK_LOWER --fsk_upper=$FSK_UPPER - - | python3 -m horusdemodlib.uploader --freq_hz $SDR_RX_FREQ --freq_target_hz $RXFREQ $@

Wyświetl plik

@ -0,0 +1,38 @@
#!/usr/bin/env bash
#
# Horus Binary RTLSDR Helper Script
#
# Uses rtl_fm to receive a chunk of spectrum, and passes it into horus_demod.
#
# Calculate the SDR tuning frequency
SDR_RX_FREQ=$(echo "$RXFREQ - $RXBANDWIDTH/2 - 1000" | bc)
# Calculate the frequency estimator limits
FSK_LOWER=1000
FSK_UPPER=$(echo "$FSK_LOWER + $RXBANDWIDTH" | bc)
echo "Using SDR Centre Frequency: $SDR_RX_FREQ Hz."
echo "Using FSK estimation range: $FSK_LOWER - $FSK_UPPER Hz"
BIAS_SETTING=""
if [ "$BIAS" = "1" ]; then
echo "Enabling Bias Tee."
BIAS_SETTING=" -T"
fi
GAIN_SETTING=""
if [ "$GAIN" = "0" ]; then
echo "Using AGC."
GAIN_SETTING=""
else
echo "Using Manual Gain"
GAIN_SETTING=" -g $GAIN"
fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($SDR_RX_FREQ) and 'target' signal frequency ($RXFREQ)
# to enable providing additional metadata to Habitat / Sondehub.
rx_fm $SDR_EXTRA -M raw -F9 -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $SDR_RX_FREQ | $DECODER -q --stats=5 -g -m binary --fsk_lower=$FSK_LOWER --fsk_upper=$FSK_UPPER - - | python3 -m horusdemodlib.uploader --freq_hz $SDR_RX_FREQ --freq_target_hz $RXFREQ $@

Wyświetl plik

@ -63,3 +63,5 @@ add_definitions(-DHORUS_L2_RX -DINTERLEAVER -DSCRAMBLER -DRUN_TIME_TABLES)
add_executable(horus_demod horus_demod.c horus_api.c horus_l2.c golay23.c fsk.c kiss_fft.c)
target_link_libraries(horus_demod m horus ${CMAKE_REQUIRED_LIBRARIES})
install(TARGETS fsk_mod fsk_demod fsk_get_test_bits fsk_put_test_bits drs232 drs232_ldpc horus_gen_test_bits horus_demod DESTINATION bin)

Wyświetl plik

@ -53,7 +53,7 @@ int main(int argc, char *argv[]) {
float loop_time;
int enable_stats = 0;
int quadrature = 0;
int fsk_lower = -1;
int fsk_lower = -99999;
int fsk_upper = -1;
int Rs = -1;
int tone_spacing = -1;
@ -224,9 +224,11 @@ int main(int argc, char *argv[]) {
stats_ctr = 0;
}
if((fsk_lower> 0) && (fsk_upper > fsk_lower)){
if((fsk_upper > fsk_lower) && (fsk_lower > -99999)){
horus_set_freq_est_limits(hstates, fsk_lower, fsk_upper);
fprintf(stderr,"Setting estimator limits to %d to %d Hz.\n",fsk_lower, fsk_upper);
} else {
printf(stderr,"Not setting estimator limits, upper must be higher than lower.");
}

Wyświetl plik

@ -3,7 +3,8 @@
//
// An approximation of the function
//
// This file is generated by the gen_phi0 scritps
// This file is generated by the gen_phi0 script, from codec2
// https://github.com/drowe67/codec2/blob/master/script/gen_phi0
// Any changes should be made to that file, not this one
#include <stdint.h>

Wyświetl plik

@ -29,6 +29,11 @@ MFSK2_SIGNAL=15000
# but the higher the chance that the modem will lock on to a strong spurious signal.
RXBANDWIDTH=5000
# RTLSDR Device Selection
# If you want to use a specific RTLSDR, you can change this setting to match the
# device identifier of your SDR (use rtl_test to get a list)
SDR_DEVICE=0
# Receiver Gain. Set this to 0 to use automatic gain control, otherwise if running a
# preamplifier, you may want to experiment with different gain settings to optimize
# your receiver setup.
@ -113,4 +118,4 @@ fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($RXFREQ) and 'target' signal frequency ($MFSK1_CENTRE)
# to enable providing additional metadata to Habitat / Sondehub.
rtl_fm -M raw -F9 -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ | tee >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK1_LOWER --fsk_upper=$MFSK1_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK1_CENTRE ) >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK2_LOWER --fsk_upper=$MFSK2_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ ) > /dev/null
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ | tee >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK1_LOWER --fsk_upper=$MFSK1_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK1_CENTRE ) >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK2_LOWER --fsk_upper=$MFSK2_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ ) > /dev/null

Wyświetl plik

@ -31,6 +31,11 @@ MFSK_SIGNAL=15000
# but the higher the chance that the modem will lock on to a strong spurious signal.
RXBANDWIDTH=8000
# RTLSDR Device Selection
# If you want to use a specific RTLSDR, you can change this setting to match the
# device identifier of your SDR (use rtl_test to get a list)
SDR_DEVICE=0
# Receiver Gain. Set this to 0 to use automatic gain control, otherwise if running a
# preamplifier, you may want to experiment with different gain settings to optimize
# your receiver setup.
@ -115,4 +120,4 @@ fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($RXFREQ) and 'target' signal frequency ($RTTY_CENTRE / $MFSK_CENTRE)
# to enable providing additional metadata to Habitat / Sondehub.
rtl_fm -M raw -F9 -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ | tee >($DECODER -q --stats=5 -g -m RTTY --fsk_lower=$RTTY_LOWER --fsk_upper=$RTTY_UPPER - - | python -m horusdemodlib.uploader --rtty --freq_hz $RXFREQ --freq_target_hz $RTTY_CENTRE ) >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK_LOWER --fsk_upper=$MFSK_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK_CENTRE ) > /dev/null
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ | tee >($DECODER -q --stats=5 -g -m RTTY --fsk_lower=$RTTY_LOWER --fsk_upper=$RTTY_UPPER - - | python -m horusdemodlib.uploader --rtty --freq_hz $RXFREQ --freq_target_hz $RTTY_CENTRE ) >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK_LOWER --fsk_upper=$MFSK_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK_CENTRE ) > /dev/null

Wyświetl plik

@ -15,6 +15,12 @@ cd /home/pi/horusdemodlib/
# Note: The SDR will be tuned to RXBANDWIDTH/2 below this frequency.
RXFREQ=434200000
# RTLSDR Device Selection
# If you want to use a specific RTLSDR, you can change this setting to match the
# device identifier of your SDR (use rtl_test to get a list)
SDR_DEVICE=0
# Receiver Gain. Set this to 0 to use automatic gain control, otherwise if running a
# preamplifier, you may want to experiment with different gain settings to optimize
# your receiver setup.
@ -91,4 +97,4 @@ fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($SDR_RX_FREQ) and 'target' signal frequency ($RXFREQ)
# to enable providing additional metadata to Habitat / Sondehub.
rtl_fm -M raw -F9 -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $SDR_RX_FREQ | $DECODER -q --stats=5 -g -m binary --fsk_lower=$FSK_LOWER --fsk_upper=$FSK_UPPER - - | python -m horusdemodlib.uploader --freq_hz $SDR_RX_FREQ --freq_target_hz $RXFREQ $@
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $SDR_RX_FREQ | $DECODER -q --stats=5 -g -m binary --fsk_lower=$FSK_LOWER --fsk_upper=$FSK_UPPER - - | python -m horusdemodlib.uploader --freq_hz $SDR_RX_FREQ --freq_target_hz $RXFREQ $@

Wyświetl plik

@ -0,0 +1,136 @@
#!/usr/bin/env bash
#
# Horus Binary *Triple* Decoder Script
# Intended for situations with three payloads in the air, spaced ~10 kHz apart.
# NOTE - Ensure your horus_demod build is from newer than ~5th April 2024, else this
# will not work correctly!
#
# It also possible to extend this approach further to handle as many transmissions
# as can be safely fitted into the receiver passband (+/- 24 kHz). Spacings of
# 5 kHz between transmissions is possible with frequency stable transmitters (e.g. RS41s)
# Don't try this with DFM17's, which drift a lot!
#
# Change directory to the horusdemodlib directory.
# If running as a different user, you will need to change this line
cd /home/pi/horusdemodlib/
# The following settings are an example for a situation where there are three transmitters in the air,
# on: 434.190 MHz, 434.200 MHz, and 434.210 MHz.
# The *centre* frequency of the SDR Receiver, in Hz.
# It's recommended that this not be tuned directly on top of one of the signals we want to receive,
# as sometimes we can get a DC spike which can affect the demodulators.
# In this example the receiver has been tuned in the middle of 2 of the signals, at 434.195 MHz.
RXFREQ=434195000
# Where to find the first signal - in this case at 434.190 MHz, so -5000 Hz below the centre.
MFSK1_SIGNAL=-5000
# Where to find the second signal - in this case at 434.200 MHz, so 5000 Hz above the centre.
MFSK2_SIGNAL=5000
# Where to find the third signal - in this case at 434.210 MHz, so 15000 Hz above the centre.
MFSK3_SIGNAL=15000
# Frequency estimator bandwidth. The wider the bandwidth, the more drift and frequency error the modem can tolerate,
# but the higher the chance that the modem will lock on to a strong spurious signal.
RXBANDWIDTH=8000
# RTLSDR Device Selection
# If you want to use a specific RTLSDR, you can change this setting to match the
# device identifier of your SDR (use rtl_test to get a list)
SDR_DEVICE=0
# Receiver Gain. Set this to 0 to use automatic gain control, otherwise if running a
# preamplifier, you may want to experiment with different gain settings to optimize
# your receiver setup.
# You can find what gain range is valid for your RTLSDR by running: rtl_test
GAIN=0
# Bias Tee Enable (1) or Disable (0)
# NOTE: This uses the -T bias-tee option which is only available on recent versions
# of rtl-sdr. Check if your version has this option by running rtl_fm --help and looking
# for it in the option list.
# If not, you may need to uninstall that version, and then compile from source: https://github.com/osmocom/rtl-sdr
BIAS=0
# Receiver PPM offset
PPM=0
# Check that the horus_demod decoder has been compiled.
DECODER=./build/src/horus_demod
if [ -f "$DECODER" ]; then
echo "Found horus_demod."
else
echo "ERROR - $DECODER does not exist - have you compiled it yet?"
exit 1
fi
# Check that bc is available on the system path.
if echo "1+1" | bc > /dev/null; then
echo "Found bc."
else
echo "ERROR - Cannot find bc - Did you install it?"
exit 1
fi
# Use a local venv if it exists
VENV_DIR=venv
if [ -d "$VENV_DIR" ]; then
echo "Entering venv."
source $VENV_DIR/bin/activate
fi
# Calculate the frequency estimator limits for each decoder
MFSK1_LOWER=$(echo "$MFSK1_SIGNAL - $RXBANDWIDTH/2" | bc)
MFSK1_UPPER=$(echo "$MFSK1_SIGNAL + $RXBANDWIDTH/2" | bc)
MFSK1_CENTRE=$(echo "$RXFREQ + $MFSK1_SIGNAL" | bc)
MFSK2_LOWER=$(echo "$MFSK2_SIGNAL - $RXBANDWIDTH/2" | bc)
MFSK2_UPPER=$(echo "$MFSK2_SIGNAL + $RXBANDWIDTH/2" | bc)
MFSK2_CENTRE=$(echo "$RXFREQ + $MFSK2_SIGNAL" | bc)
MFSK3_LOWER=$(echo "$MFSK3_SIGNAL - $RXBANDWIDTH/2" | bc)
MFSK3_UPPER=$(echo "$MFSK3_SIGNAL + $RXBANDWIDTH/2" | bc)
MFSK3_CENTRE=$(echo "$RXFREQ + $MFSK3_SIGNAL" | bc)
echo "Using SDR Centre Frequency: $RXFREQ Hz."
echo "Using MFSK1 estimation range: $MFSK1_LOWER - $MFSK1_UPPER Hz"
echo "Using MFSK2 estimation range: $MFSK2_LOWER - $MFSK2_UPPER Hz"
echo "Using MFSK3 estimation range: $MFSK3_LOWER - $MFSK3_UPPER Hz"
BIAS_SETTING=""
if [ "$BIAS" = "1" ]; then
echo "Enabling Bias Tee."
BIAS_SETTING=" -T"
fi
GAIN_SETTING=""
if [ "$GAIN" = "0" ]; then
echo "Using AGC."
GAIN_SETTING=""
else
echo "Using Manual Gain"
GAIN_SETTING=" -g $GAIN"
fi
STATS_SETTING=""
if [ "$STATS_OUTPUT" = "1" ]; then
echo "Enabling Modem Statistics."
STATS_SETTING=" --stats=100"
fi
# Start the receive chain.
# Note that we now pass in the SDR centre frequency ($RXFREQ) and 'target' signal frequency ($MFSK1_CENTRE)
# to enable providing additional metadata to SondeHub
rtl_fm -M raw -F9 -d $SDR_DEVICE -s 48000 -p $PPM $GAIN_SETTING$BIAS_SETTING -f $RXFREQ \
| tee >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK1_LOWER --fsk_upper=$MFSK1_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK1_CENTRE ) \
| tee >($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK3_LOWER --fsk_upper=$MFSK3_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ --freq_target_hz $MFSK3_CENTRE ) \
>($DECODER -q --stats=5 -g -m binary --fsk_lower=$MFSK2_LOWER --fsk_upper=$MFSK2_UPPER - - | python -m horusdemodlib.uploader --freq_hz $RXFREQ ) > /dev/null

Wyświetl plik

@ -3,8 +3,7 @@
#
[user]
# Your callsign - used when uploading to the HabHub Tracker.
# Note that we now also upload to the experimental SondeHub Amateur DB as well by default.
# Your callsign - used when uploading to the SondeHub-Amateur Tracker
callsign = YOUR_CALL_HERE
# Your station latitude/longitude, which will show up on tracker.habhub.org.

98
user.env.example 100644
Wyświetl plik

@ -0,0 +1,98 @@
### General SDR settings ###
# RTLSDR Device Selection
# If you want to use a specific RTLSDR, you can change this setting to match the
# device identifier of your SDR (use rtl_test to get a list)
SDR_DEVICE=0
# Receiver Gain. Set this to 0 to use automatic gain control, otherwise if running a
# preamplifier, you may want to experiment with different gain settings to optimize
# your receiver setup.
# You can find what gain range is valid for your RTLSDR by running: rtl_test
GAIN=0
# Bias Tee Enable (1) or Disable (0)
BIAS=0
# Receiver PPM offset
PPM=0
# Enable (1) or disable (0) modem statistics output.
# If enabled, modem statistics are written to stats.txt, and can be observed
# during decoding by running: tail -f stats.txt | python fskstats.py
STATS_OUTPUT=0
# Select decoder to tun
DECODER=horus_demod
# For use with SoapySDR via rx_tools
#SDR_EXTRA="-d driver=rtlsdr"
##########################################################
### NOTE: Only uncomment one of the settings sections! ###
##########################################################
### Single 4FSK settings ###
# Script name
DEMODSCRIPT="docker_single.sh"
# Receive *centre* frequency, in Hz
# Note: The SDR will be tuned to RXBANDWIDTH/2 below this frequency.
RXFREQ=434200000
# Frequency estimator bandwidth. The wider the bandwidth, the more drift and frequency error the modem can tolerate,
# but the higher the chance that the modem will lock on to a strong spurious signal.
# Note: The SDR will be tuned to RXFREQ-RXBANDWIDTH/2, and the estimator set to look at 0-RXBANDWIDTH Hz.
RXBANDWIDTH=10000
### Dual 4FSK settings ###
# Script name
#DEMODSCRIPT="docker_dual_4fsk.sh"
# Receive requency, in Hz. This is the frequency the SDR is tuned to.
#RXFREQ=434195000
# Frequency estimator bandwidth. The wider the bandwidth, the more drift and frequency error the modem can tolerate,
# but the higher the chance that the modem will lock on to a strong spurious signal.
#RXBANDWIDTH=5000
# Where in the passband we expect to find the Lower Horus Binary (MFSK) signal, in Hz.
# For this example, this is on 434.290 MHz, so with a SDR frequency of 434.195 MHz,
# we expect to find the signal at approx +5 kHz.
# Note that the signal must be located ABOVE the centre frequency of the receiver.
#MFSK1_SIGNAL=5000
# Where in the receiver passband we expect to find the higher Horus Binary (MFSK) signal, in Hz.
# In this example, our second frequency is at 434.210 MHz, so with a SDR frequency of 434.195 MHz,
# we expect to find the signal at approx +15 kHz.
#MFSK2_SIGNAL=15000
## Dual RTTY 4FSK settings ###
# Script name
#DEMODSCRIPT="docker_dual_rtty_4fsk.sh"
# Receive requency, in Hz. This is the frequency the SDR is tuned to.
#RXFREQ=434645000
# Frequency estimator bandwidth. The wider the bandwidth, the more drift and frequency error the modem can tolerate,
# but the higher the chance that the modem will lock on to a strong spurious signal.
#RXBANDWIDTH=8000
# Where in the passband we expect to find the RTTY signal, in Hz.
# For Horus flights, this is on 434.650 MHz, so with a SDR frequency of 434.645 MHz,
# we expect to find the RTTY signal at approx +5 kHz.
# Note that the signal must be located ABOVE the centre frequency of the receiver.
#RTTY_SIGNAL=5000
# Where in the receiver passband we expect to find the Horus Binary (MFSK) signal, in Hz.
# For Horus flights, this is on 434.660 MHz, so with a SDR frequency of 434.645 MHz,
# we expect to find the RTTY signal at approx +15 kHz.
#MFSK_SIGNAL=15000