Support for Typhur Sync Gold Dual/Quad
I started looking into how to add support for this meat thermometer. I have the dual version, so the captures I had were from both probes running at once. These have 6 different temperature sensors (5 internal & one ambient) per probe so it ought to be fun to fully decode.
Here's what I've gathered so far: typhur-sync-gold-samples.zip. I'm not positive, but based just visual observation from a few of these files at https://triq.org/pdv/, I think there is some other 915MHz-band traffic flying around too.
Those were captured with temperatures around ~210-230F for the Ambient Sensors, and ~140F-165F Internal Temperatures for the internal probe sensors (next time I take a stab at this I'll get more exact)
Some things that looked pattern-y with rtl_433 -A -r, especially for files in the auto-decoded folder. The suggested decoder was rtl_433 -R 0 -X 'n=name,m=FSK_PCM,s=12,l=12,r=12288' *.cs16
{280}d5555555555555552baa10df00507a2bb00df18dc40da80d9c8da1820800ed8546de00
{279}00000000000000002baa10df00507a2bb20df18dcb8dad0da18da1820800ef8514a83e
{279}0000000000000000035461b100a0f457cb1e711ccb1cfe1c341d0d040101f90a8f7f02
{280}fd555555555555552baa10df00507a2bb20df18dcc0daf8da40da1820800f18559d580
{280}00000000000000002baa30d880507a2be60f388e658e7f0e1a8e87020080fe850eb580
Maybe preamble=0507a2b based on the above? But wasn't obvious to me why those earlier bits were changing.
One example of decoded data here
Full command line output for one capture
rtl_433 version 24.10 (2024-10-30) inputs file rtl_tcp RTL-SDR with TLS
[Input] Test mode active. Reading samples from file: g019_915M_1000k.cs16
Detected FSK package @0.014538s
Analyzing pulses...
Total count: 35, width: 11.97 ms (11969 S)
Pulse width distribution:
[ 0] count: 1, width: 0 us [0;0] ( 0 S)
[ 1] count: 22, width: 103 us [98;105] ( 103 S)
[ 2] count: 2, width: 470 us [418;522] ( 470 S)
[ 3] count: 6, width: 208 us [208;211] ( 208 S)
[ 4] count: 2, width: 313 us [312;314] ( 313 S)
[ 5] count: 1, width: 728 us [728;728] ( 728 S)
[ 6] count: 1, width: 4 us [4;4] ( 4 S)
Gap width distribution:
[ 0] count: 1, width: 1042 us [1042;1042] (1042 S)
[ 1] count: 28, width: 103 us [92;106] ( 103 S)
[ 2] count: 2, width: 208 us [208;208] ( 208 S)
[ 3] count: 2, width: 469 us [417;521] ( 469 S)
[ 4] count: 1, width: 833 us [833;833] ( 833 S)
Pulse period distribution:
[ 0] count: 2, width: 990 us [938;1042] ( 990 S)
[ 1] count: 20, width: 207 us [195;209] ( 207 S)
[ 2] count: 4, width: 573 us [522;626] ( 573 S)
[ 3] count: 5, width: 313 us [311;314] ( 313 S)
[ 4] count: 1, width: 416 us [416;416] ( 416 S)
[ 5] count: 2, width: 780 us [729;832] ( 780 S)
Pulse timing distribution:
[ 0] count: 1, width: 0 us [0;0] ( 0 S)
[ 1] count: 50, width: 103 us [92;106] ( 103 S)
[ 2] count: 4, width: 469 us [417;522] ( 469 S)
[ 3] count: 8, width: 208 us [208;211] ( 208 S)
[ 4] count: 2, width: 313 us [312;314] ( 313 S)
[ 5] count: 2, width: 780 us [728;833] ( 780 S)
[ 6] count: 1, width: 4 us [4;4] ( 4 S)
[ 7] count: 1, width: 1042 us [1042;1042] (1042 S)
[ 8] count: 1, width: 0 us [0;0] ( 0 S)
Level estimates [high, low]: 1000, 210
RSSI: -24.3 dB SNR: 13.6 dB Noise: -37.8 dB
Frequency offsets [F1, F2]: 1721, -2926 (+26.3 kHz, -44.6 kHz)
Guessing modulation: No clue...
Detected FSK package @0.086616s
Analyzing pulses...
Total count: 78, width: 3.41 ms ( 3409 S)
Pulse width distribution:
[ 0] count: 4, width: 65 us [62;74] ( 65 S)
[ 1] count: 52, width: 12 us [11;14] ( 12 S)
[ 2] count: 4, width: 37 us [36;38] ( 37 S)
[ 3] count: 16, width: 24 us [24;27] ( 24 S)
[ 4] count: 2, width: 50 us [50;50] ( 50 S)
Gap width distribution:
[ 0] count: 55, width: 12 us [11;14] ( 12 S)
[ 1] count: 5, width: 25 us [25;26] ( 25 S)
[ 2] count: 4, width: 49 us [48;51] ( 49 S)
[ 3] count: 2, width: 124 us [112;137] ( 124 S)
[ 4] count: 6, width: 66 us [62;75] ( 66 S)
[ 5] count: 5, width: 37 us [36;39] ( 37 S)
Pulse period distribution:
[ 0] count: 11, width: 75 us [61;88] ( 75 S)
[ 1] count: 41, width: 24 us [24;27] ( 24 S)
[ 2] count: 11, width: 37 us [37;39] ( 37 S)
[ 3] count: 9, width: 54 us [49;64] ( 54 S)
[ 4] count: 2, width: 162 us [150;174] ( 162 S)
[ 5] count: 3, width: 100 us [99;101] ( 100 S)
Pulse timing distribution:
[ 0] count: 10, width: 66 us [62;75] ( 66 S)
[ 1] count: 107, width: 12 us [11;14] ( 12 S)
[ 2] count: 9, width: 37 us [36;39] ( 37 S)
[ 3] count: 21, width: 25 us [24;27] ( 25 S)
[ 4] count: 6, width: 49 us [48;51] ( 49 S)
[ 5] count: 2, width: 124 us [112;137] ( 124 S)
[ 6] count: 1, width: 87 us [87;87] ( 87 S)
Level estimates [high, low]: 2647, 197
RSSI: -15.8 dB SNR: 22.6 dB Noise: -38.4 dB
Frequency offsets [F1, F2]: 2630, -1691 (+40.1 kHz, -25.8 kHz)
Guessing modulation: Non Return to Zero coding (Pulse Code)
view at https://triq.org/pdv/#AAB03407010042000C002500190031007C00578191919191919191919191919191919191919191919191919191919191939191A191919455+AAB01107010042000C002500190031007C00579455+AAB01207010042000C002500190031007C0057B18555+AAB01207010042000C002500190031007C0057919055+AAB01707010042000C002500190031007C0057C1929191A1B39055+AAB01607010042000C002500190031007C0057B182B2B1A3B055+AAB01807010042000C002500190031007C0057B1B19182B1B1939055+AAB01307010042000C002500190031007C0057B1B19455+AAB01107010042000C002500190031007C0057B055+AAB01107010042000C002500190031007C00579055+AAB01107010042000C002500190031007C00579555+AAB01207010042000C002500190031007C0057C2B455+AAB01807010042000C002500190031007C0057919191B3A19191B655
Attempting demodulation... short_width: 12, long_width: 12, reset_limit: 12288, sync_width: 0
Use a flex decoder with -X 'n=name,m=FSK_PCM,s=12,l=12,r=12288'
[pulse_slicer_pcm] Analyzer Device
codes : {280}fd555555555555552baa10df00507a2bb20df18dcc0daf8da40da1820800f18559d580
Product link: https://www.typhur.com/products/sync-gold-dual or https://www.typhur.com/products/sync-gold-quad
FCC Info - I think this is for the probe: https://fccid.io/2BEFM-WTP3000. This is for the base: https://fccid.io/2BEFM-WT1000R
The base also has Bluetooth and Wifi support (started reverse-engineering the Wifi here), so it would be possible to capture data that way too, but I figured the RF data would be fun too.
It seems there are three different senders in the samples, the slower signal at 915.0M, e.g. g021_915M_1000k.cs16, then the fast signal at 915.0M, e.g. g005_915M_1000k.cs16 and lastly the slow signal at 914.6M, e.g. g009_915M_1000k.cs16. And some others too like the first one in g015_915M_1000k.cs16.
You need to narrow it down in a quieter environment or without antenna and close to the sender.
12 µs sounds awefully fast for just a temperature probe.
Status? I'm not sure this issue has enough useful info to keep open, without a reason to think we're having progress.
Hi! With some help from a friend (that made the GNU Radio chain) I've managed to decode temperatures 1 to 5.
It would be nice to collaborate with someone familiar with RF work and C. I have no prior experience to speak of in RF work or C coding.
Parameters: 915Mhz center freq 80Khz wide (two peaks at +-40Khz from center) GFSK modulation 80kbps baud rate / 12.5 µs data packet is around ~27 bytes / ~216 bits 25 sps at 2Msps
Attached is a csv file of bits from the probe's broadcast and their corresponding temperaturesq (last 5 columns are calculated, the binary data before that is from gnuradio). I haven't worked out what the other fields are yet.
Typhur demodulated data work - binary data.csv
Graph (probe in ice water -> to a kettle with water and set to boil -> removed from kettle):
I have two identical probes but I loaned one to a friend. When I get it back I will capture its broadcast and compare to the one I have now. I think the first bytes in the payload are the probes serial/id, but will confirm when I get the second probe back.
How to decode temperatures: Example snippet from broadcast for one of the 5 main temp sensors. Example should be around ~55°C:
example payload of TEMP1:
1011010010001010
split into two bytes (high | low)
10110100 | 10001010
swap to little endian (low first, then high)
10001010 10110100
mask the MSB (clear the first bit)
before: 10001010 10110100
after: 00001010 10110100
convert to decimal:
0000101010110100 = 2740
convert to celcius:
2740 / 50 = 54.8°C
This formula matches the data the base reports:
Thanks for confirming the 12 µs timing and the comprehensive analysis of the probes.
Does the g005_915M_1000k.cs16 sample file from the samples above work with your decoding? Or can you grab a .cu8 or .cs16 sample file?
Something like the mentioned rtl_433 -R 0 -X 'n=name,m=FSK_PCM,s=12,l=12,r=300' should work to get data.
@hakong thanks for all the detailed info! Basically you found the format to be
SYNC_WORD:48h TYPE:8h SUB:8h TEMP1:16h TEMP2:16h TEMP3:16h TEMP4:16h TEMP5:16h T_AMB:8h BATT:8h FLAG:8h COUNTER:24h CRC:8h, right?
What values did you get for SYNC_WORD:, TYPE, and SUB?
These are just guesses. To confirm I have yet to pick up my 2nd probe and compare them. I'll pick up my 2nd probe tomorrow.
- sync word/probe id: TODO: distginguish between the probes (i suspect the sync word is a form of probe ID/serial, since the app has support for multiple probes and "pairing" them. i can see my probe's serial number in the app)
- type/subtype: TODO: see if there is any difference between the two probes, and see if there is a difference between packets when the probe is charging/discharging.
- temp1-5: done
- temp ambient: TODO: figure out the encoding
- batt: just a guess. TODO: let the probes battery drain to 50% and check what values I get
- flag: just a guess. TODO: compare between 2 probes if any difference
- counter: looks like a counter, at least increments by 32 every 2 brodcasts if decoded in little endian 15 bit MSB masked. TODO: try other decodings
- CRC: just a guess, shouldn't there be a CRC at the end of brodcasts like this?
@zuckschwerdt helped me get started on decoding this, here is the format of the payload laid out in bitbench
I've put together a decoder for rtl_433 with the help of an LLM, but since I'm not experienced in C or this kind of bit decoding work, I would like someone to go over the code and scrutinize. I understand it for the most part but there are a few parts that go a bit over my head.
Here is the initial code: https://github.com/hakong/rtl_433/commit/bdf718296af5df1963071394e337cfaa3da916a0
Can someone take a look?
I'm currently short on time, I plan to write a decoder. The LLM code is not useable, it breaks our coding style and conventions in nearly every line.
Ok, good to hear. I suspected the LLM code would not be good enough, but maybe parts of it would be usable. It's also just a draft, I left a bit of debug code in there which I would have removed. It does however work :) I've compiled it and been using it for a few days now to collect data.
Looking forward to see the difference!
I don't think it's ok to ask people to clean up LLM code. Plus, most (all) LLMs are trained on stolen content and thus don't comply with Free Software licensing norms.
Fully agree. Though I do find the code interesting to read, it's working and generally does the right thing. It's however very far off our code style and does not integrate (e.g. the CRC and debug output).
And @hakong was completely transparent and very politely asked me about LLM policy beforehand, I just didn't answer in time.
Yes, I agree. Thank you for the comments. I know LLM code is at controversial and maybe rarely usable on its own. That's why I was transparent about it. I don't want to push code on someone else and tell them its mine when it's written by an LLM. Especially so when it's in a language that I'm not proficient in. Again, that's exactly why I am transparent about it.
This was more of a draft/demo I thought was a non-zero chance it would be at least in some part usable (since it does compile and works).
rtl_433 version 25.02-47-g5827699d branch feat-typhur at 202509092028 inputs file rtl_tcp RTL-SDR with TLS
New defaults active, use "-Y classic -s 250k" if you need the old defaults
Found Rafael Micro R820T tuner
[SDR] Using device 0: Realtek, RTL2838UHIDIR, SN: 00000001, "Generic RTL2832U OEM"
Exact sample rate is: 1000000.026491 Hz
[R82XX] PLL not locked!
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time : 2025-09-13 09:31:15
model : Typhur-SyncGold id : 2467328
in_base : 0 unknown1_hex: 0xA0 unknown2_hex: 0x57 counter : 12 s : 24 on_since_approx: 2025-09-13T09:30:51Z V : 2.830 C : 23.240 C : 23.390
C : 23.380 C : 23.340 C : 23.380 C : 24.900 message : base=0 cnt=12 up=24s core_min=23.24C core_max=23.39C
codes : 25A600A0F4571409230922091E092209F9001B010C00E210 mic : CRC
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time : 2025-09-13 09:31:17
model : Typhur-SyncGold id : 2467328
in_base : 0 unknown1_hex: 0xA0 unknown2_hex: 0x57 counter : 13 s : 26 on_since_approx: 2025-09-13T09:30:51Z V : 2.830 C : 23.240 C : 23.390
C : 23.380 C : 23.340 C : 23.380 C : 24.900 message : base=0 cnt=13 up=26s core_min=23.24C core_max=23.39C
codes : 25A600A0F4571409230922091E092209F9001B010D006413 mic : CRC
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time : 2025-09-13 09:31:19
model : Typhur-SyncGold id : 2467328
in_base : 0 unknown1_hex: 0xA0 unknown2_hex: 0x57 counter : 14 s : 28 on_since_approx: 2025-09-13T09:30:51Z V : 2.830 C : 23.240 C : 23.390
C : 23.380 C : 23.340 C : 23.380 C : 24.900 message : base=0 cnt=14 up=28s core_min=23.24C core_max=23.39C
codes : 25A600A0F4571409230922091E092209F9001B010E006E13 mic : CRC
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time : 2025-09-13 09:31:21
model : Typhur-SyncGold id : 2467328
in_base : 0 unknown1_hex: 0xA0 unknown2_hex: 0x57 counter : 15 s : 30 on_since_approx: 2025-09-13T09:30:51Z V : 2.830 C : 23.240 C : 23.390
C : 23.380 C : 23.340 C : 23.380 C : 24.900 message : base=0 cnt=15 up=30s core_min=23.24C core_max=23.39C
codes : 25A600A0F4571409230922091E092209F9001B010F00E810 mic : CRC
I don't think it's ok to ask people to clean up LLM code. Plus, most (all) LLMs are trained on stolen content and thus don't comply with Free Software licensing norms.
I had a thought and it is hard to clearly assign copyright to LLM generated code. But derived code could possibly be licensed under the GPL. In this case the LLM code used a couple of api calls and must thus be derived and is then covered under the GPL license.
But I think we should adopt the policy of rejecting LLM contributions until there is a general consensus about LLM code among other open source projects. I think it would be safe to adopt anything that is also accepted by the Linux kernel (but we dont have to).
The PoC is impressive though but you have a very structured problem and a large set of decoder to train a LLM on. You can get quick results and then reference the code when re-implementing it. It would be interesting if a LLM could be made to decode a set of messages to parameters.
If there is any interest, here is a refactored version that is closer to matching the code style of rtl_433. https://github.com/hakong/rtl_433/blob/feat-typhur/src/devices/typhur_sync_gold.c