<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: D</title>
    <description>The latest articles on DEV Community by D (@a3xt).</description>
    <link>https://dev.to/a3xt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3686877%2Fd4a1d4a7-ae2a-46d0-a737-77ddfd32a394.png</url>
      <title>DEV Community: D</title>
      <link>https://dev.to/a3xt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/a3xt"/>
    <language>en</language>
    <item>
      <title>Keen Electronics Key Fob</title>
      <dc:creator>D</dc:creator>
      <pubDate>Thu, 19 Feb 2026 05:19:04 +0000</pubDate>
      <link>https://dev.to/a3xt/keen-electronics-key-fob-48kk</link>
      <guid>https://dev.to/a3xt/keen-electronics-key-fob-48kk</guid>
      <description>&lt;p&gt;I stumbled across an old 2-buttoned key fob&lt;/p&gt;

&lt;p&gt;The RF output is intended for 433.92 MHz but uses a SAW resonator and the exact resultant frequency flies around depending on temperature, pressure, and whether or not the tide is high on the opposite side of the planet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Product
&lt;/h2&gt;

&lt;p&gt;It's a small keychain fob with two (2) buttons and a green LED. It features the company name &lt;a href="https://find-and-update.company-information.service.gov.uk/company/02613501" rel="noopener noreferrer"&gt;Keen Electronics Ltd.&lt;/a&gt; (dissolved as of November 2025) with the phone number 01296 423203 on the front and a serial number sticker on the back reading 000984.&lt;/p&gt;

&lt;p&gt;It's an old fob. The rubber buttons have become incredibly soft like chewing gum. When I press the button, it stays permanently deformed to my finger. Opening it up, it uses an NM21/23 12 VDC battery. The PCB is marked "AMTX2B-4-ER" which does yield some results but nothing especially technical. It seems like these are generic hardcoded fobs. The unit still works. The green LED appears strong but appears to flicker ever so slightly. When I shake it with the LED lighting up, I can see the actual LED strobing to the RF signal it's sending.&lt;/p&gt;

&lt;p&gt;There are two (2) buttons which have completely lost their identity I will refer to as simply "left" or "right." The fob also indicates that pressing both buttons together is a "panic mode" which just serves as a third button.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Radio
&lt;/h2&gt;

&lt;p&gt;The fob transmits somewhere in the ballpark of 433.83 MHz in my case. The encoded data is done with a type of On-Off Keying (OOK) called Pulse Distance Modulation (PDM). The on pulses remain short at a fixed length, the distances between the pulses convey the data.&lt;/p&gt;

&lt;p&gt;I did try my best to quantise the PHY durations but the quanta timing seems almost arbitrarily chosen. There is a wakeup pulse which is long, then a long distance, then begins consistently spaced on/off signals, then a distance different to the others. Essentially, there are 2 different on durations and 4 different gaps. The anomolous distances sorta-kinda match half distances so I crunched my findings down as such and I'm fine with that for now.&lt;/p&gt;

&lt;p&gt;The SAW resonator means the output radio frequency flies all over the place during transmission but the most consistent pulse duration I measured was around 460 microseconds. Half that to make sense of the arbitrary timing; so 230 microseconds and pair them together when needed.&lt;/p&gt;

&lt;p&gt;I wonder if the weird non-uniformity of the timing is a result of these fobs being manufactured as duplicators from another RF generator source and the signal was badly attentuated or something, instead of being directly programmed onto the board.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Data
&lt;/h2&gt;

&lt;p&gt;There are essentially three (3) different packets being sent; left button, right button, and both buttons pressed (for "panic" function).&lt;/p&gt;

&lt;p&gt;Again, due to the weird timing, I have derived the following symbols:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"S" = 00111111111111111000000000000000
"0" = 1100
"1" = 1100000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Armed with this information, I can compile the left, right, and panic packets into the following stream of symbols:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S 10000111 10000011 10000000 00010101 01010000 01010100 00000000
S 10000111 10000011 10000000 00100101 01010000 01010100 00000000
S 10000111 10000011 10000000 00110101 01010000 01010100 00000000
                               ^^
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately, my interpretation of the timing means it fits nicely into 7 complete bytes and we can see these are all identical other than 2 bits indicating the button.&lt;/p&gt;

&lt;p&gt;Before we get too excited, bear in mind that the packet repeats a maximum 6 times. After the sixth packet, a final symbol "S" is appended.&lt;/p&gt;

&lt;p&gt;Here is what a full transmission looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznyyjkxrlwig0md5fa2n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznyyjkxrlwig0md5fa2n.png" alt="Full transmission of an RF signal" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Protocol
&lt;/h2&gt;

&lt;p&gt;A bit of digging around at some Texas Instruments ICs for PDM implementations, it seems to be common to encode this way for infrared remote controls, not necessarily with radio frequencies. Their page &lt;a href="https://www.ti.com/lit/an/slaa644b/slaa644b.pdf?ts=1771397704127" rel="noopener noreferrer"&gt;Infrared Remote Control Implementations&lt;/a&gt; (page 8) suggests what I call symbol "S" (for sync) they call the leading code which is defined by milliseconds instead of being quantised like the rest of the real data.&lt;/p&gt;

&lt;p&gt;After a very short test, I conclude the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There's no checksum&lt;/li&gt;
&lt;li&gt;There's no rolling code&lt;/li&gt;
&lt;li&gt;This is vulnerable to replay attacks&lt;/li&gt;
&lt;li&gt;Can be easily duplicated with a fob duplicator&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;This is all I can find out from having access to a single fob. I will need access to the radio receiver and other fobs to toy with it more and figure out what bits I can change and investigate the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What bits identify the fob ID?&lt;/li&gt;
&lt;li&gt;Are there other similarly encoded fobs with more button functionality?&lt;/li&gt;
&lt;li&gt;Is there perhaps a "master" ID that bypasses fob-specific IDs?&lt;/li&gt;
&lt;li&gt;Does the receiver support additional RF commands that the fobs don't transmit?&lt;/li&gt;
&lt;li&gt;Does the serial number label on the back of the fob have any relevance to the output of the code?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devjournal</category>
      <category>iot</category>
      <category>science</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>ThermoPro Wireless Temperature Monitors</title>
      <dc:creator>D</dc:creator>
      <pubDate>Sat, 03 Jan 2026 16:27:06 +0000</pubDate>
      <link>https://dev.to/a3xt/thermopro-wireless-temperature-monitors-5f3l</link>
      <guid>https://dev.to/a3xt/thermopro-wireless-temperature-monitors-5f3l</guid>
      <description>&lt;p&gt;ThermoPro is a company selling digital thermometers and hygrometers. They're supposedly a Canadian company with R&amp;amp;D in North America and products manufacturered in China but there are no public records that I can find that verify an actual address anywhere.&lt;/p&gt;

&lt;p&gt;They have a number of products that have wireless capability such as RF and Bluetooth. I'll be focusing on a couple of their RF products, namely the TP200C and the TP65C.&lt;/p&gt;

&lt;p&gt;I first bought the TP200C monitor and remote sensor a few months prior to using an SDR to decode its signals. I am based in the United Kingdom and the frequency listed on the cover of the product is 868 MHz. Apparently they also make units that transmit on 433 MHz but are discontinued, and make units on 915 MHz for the American market. I suspect the RF protocol is the same.&lt;/p&gt;

&lt;p&gt;I did most of the decoding process below with the transmitter that came with the temperature-only TP200C, the TX-2C. ThermoPro list the transmitter-only listing for TX-2C as being a dual thermometer and hygometer so I was a little confused because the transmitter I had was not fitted with a hygrometer sensor inside it.&lt;/p&gt;

&lt;p&gt;Curious, I bought the TP65C, a thermometer and hygrometer display, and repeated the process. The TX-2C transmitter that came with this one was fitted with a hygrometer sensor. It's trivial but I imagined the exact same product model would be built the exact same no matter what it's paired with but I guess not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visual Decoding Process
&lt;/h2&gt;

&lt;p&gt;Tuning into 868 MHz with a Software Defined Radio (SDR) shows a very distinctive signal in SDR#:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuu92v5k4nx4eeu4ykb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuu92v5k4nx4eeu4ykb4.png" alt="A waterfall view of the burst signal." width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The signal is strong with a fresh set of AAA batteries and stays mostly around 867.990 MHz so far between -1 °C and 25 °C.&lt;/p&gt;

&lt;p&gt;Focusing on that signal alone in Audacity (hey) we can quickly see what it's made of:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxxmcxhnjrg9869th4zj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxxmcxhnjrg9869th4zj.png" alt="A whole frame of data." width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's On-Off Keying (OOK) with a total burst duration of ~1.15 seconds and repeats every 50 seconds. This sits at 2.3% duty cycle already exceeding the permitted duty cycle of 1% on 868 MHz.&lt;/p&gt;

&lt;p&gt;Looking closer at the OOK signal, I can make some assumptions:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwgq4g0nx1x4dykoc309.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwgq4g0nx1x4dykoc309.png" alt="Eight frames aligned with one another to prove repetition." width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frame repeats the data eight (8) times.&lt;/li&gt;
&lt;li&gt;The last frame omits that one final pulse.&lt;/li&gt;
&lt;li&gt;The pulses are fixed-width, and the gaps vary.&lt;/li&gt;
&lt;li&gt;There are 46 pulses per frame, 45 on the last frame.&lt;/li&gt;
&lt;li&gt;The pulse is the shortest quantifiable data (a quanta) and is 474 microseconds in length.&lt;/li&gt;
&lt;li&gt;The gaps have a duration in multiples of that length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an exerpt that shows 4 different gap lengths:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfg3y3f5w8vswweiysla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfg3y3f5w8vswweiysla.png" alt="Four different gap lengths." width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can see that the bulk of the data is made up of "4" and "8" gaps, whereas "5" and "18" gaps are only used 2 and 1 times respectively. The "4" gaps were easily confused with "5" gaps and it did throw me off for a while before I caught on.&lt;/p&gt;

&lt;p&gt;It's safe to assume that the pulse can be used as a start of piece of data called a symbol and I will name these as the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Symbol "0" = 10000 (4 zeros)&lt;/li&gt;
&lt;li&gt;Symbol "1" = 100000000 (8 zeros)&lt;/li&gt;
&lt;li&gt;Symbol "S" = 100000 (5 zeros, appears twice)&lt;/li&gt;
&lt;li&gt;Symbol "L" = 1000000000000000000 (18 zeros, appears once)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can go through the whole frame and condense the signal down into a string:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygg1tjfxybuz28qhl77d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygg1tjfxybuz28qhl77d.png" alt="Identifying the bits in the signal." width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;000000SL100111110110000000000001010000110101S0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hopefully this means something to us.&lt;/p&gt;

&lt;p&gt;During this burst, the receiver displays the temperature as 2.0 °C. I raised and lowered the temperature of the remote sensor in order to see the change in data and figured out which bits relates to that. I also removed the batteries, changed the "channel" switch on the sensor, pressed the transmit button on the back of the sensor, put nearly dead batteries in, put the sensor in the freezer and in front of the heater, and I was able to split that data up in to the following fields:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;000000SL1001 11110110 0 0 00 000000010100 00110101 S0&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;000000SL1001&lt;/code&gt; never changed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;11110110&lt;/code&gt; (8-bit) is the pairing code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; is the battery low indicator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; is the force transmit button used&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;00&lt;/code&gt; is the channel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;000000010100&lt;/code&gt; is the temperature in Celsius&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;00110101&lt;/code&gt; is the humidity&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S0&lt;/code&gt; never changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now it's time to experiment. I wanted to transmit my own RF signal armed with the information above. I used an ESP32 microcontroller and a CC1101 module for transmitting/receiving RF signals. I programmed the ESP32 to send a packet of data that replicates everything above and played around with the values.&lt;/p&gt;

&lt;p&gt;Here is what I've found:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pairing Code
&lt;/h3&gt;

&lt;p&gt;The pairing code is a seemingly "random" 8-bit integer generated when batteries are put into the sensor. There is some kind of counting sequence that appears when you remove and insert the batteries repeatedly, but sometimes the number goes up, sometimes down, sometimes it's set to a noticeable bit pattern like &lt;code&gt;10101010&lt;/code&gt;, &lt;code&gt;00000000&lt;/code&gt;, &lt;code&gt;11000000&lt;/code&gt;, etc.. I think for a very low powered device, it just does what it can to pick something seemingly random so there's probably not much to it.&lt;/p&gt;

&lt;p&gt;When a receiver is paired with a sensor, the receiver will not respond to any other number. This is expected. I wondered if there was maybe a "universal" bit pattern that all receivers allow, or some kind of test pattern. Unfortunately, I did not find anything.&lt;/p&gt;

&lt;p&gt;Bits like &lt;code&gt;11111111&lt;/code&gt;, &lt;code&gt;00000000&lt;/code&gt;, &lt;code&gt;01111111&lt;/code&gt;, &lt;code&gt;10000000&lt;/code&gt;, &lt;code&gt;10101010&lt;/code&gt;, &lt;code&gt;01010101&lt;/code&gt; and so on were all tested and the receiver did not care. It only responded to the pairing code it was told to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Battery Low Indicator
&lt;/h3&gt;

&lt;p&gt;This bit is a simple 1-bit field. Zero means the battery is fine. When set, the little "battery low" icon on the display is visible indicating the batteries should be recharged or replaced. I've yet to test the threshold voltage that makes the sensor set this bit but it's not that important.&lt;/p&gt;

&lt;h3&gt;
  
  
  Force Transmit
&lt;/h3&gt;

&lt;p&gt;This bit is set when the user presses the button on the back of the unit to force it to transmit instead of waiting 50-something seconds. This is useful when pairing the sensor with the receiver. I haven't determined if the receiver actually makes use of this bit. Maybe it influences how often the receiver should poll the radio for a signal. I haven't tested that theory yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Channel Number
&lt;/h3&gt;

&lt;p&gt;This sensor and receiver can be set up with channels from 1 to 3. Some receiver units can display up to 3 remote sensors. There is a 3-position switch on the sensor for this. The signal transmits a 2-bit integer for this. A bit of &lt;code&gt;00&lt;/code&gt; is channel 1, &lt;code&gt;01&lt;/code&gt; is channel 2, and &lt;code&gt;10&lt;/code&gt; is channel 3.&lt;/p&gt;

&lt;p&gt;Obviously I tried &lt;code&gt;11&lt;/code&gt; (a theoretical channel 4) and the receiver responded as if it were channel 3.&lt;/p&gt;

&lt;p&gt;It's worth mentioning that this device does not "channelise" the 868 MHz band. It works on the same exact frequency no matter what channel you set on the device, it just changes the data within the frames only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Temperature
&lt;/h3&gt;

&lt;p&gt;This 12-bit field is the meat of the subject; this is what makes the product exist in the first place.&lt;/p&gt;

&lt;p&gt;Upon first glance and reading through the product documentation, these units have a temperature range between -20 °C and 70 °C which has been tested.&lt;/p&gt;

&lt;p&gt;With the RF signal showing &lt;code&gt;000000010100&lt;/code&gt; for the 12-bit temperature, and the receiver showing 2 °C (it's winter time), that integer is twenty (20) in decimal. After several captures, I can confirm this number needs to be devided by ten (10) to give you the decimal point. This means 21 is actually 2.1 C and so on.&lt;/p&gt;

&lt;p&gt;Below 0 °C, it's apparent this field is actually a signed integer meaning it conveys negative numbers using twos-compliment and all the bits are mostly set which again confirms these all 12 bits are used for this.&lt;/p&gt;

&lt;p&gt;Here's an example of some values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;000000000100&lt;/code&gt; = 4 = 0.4 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;000000000011&lt;/code&gt; = 3 = 0.3 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;000000000010&lt;/code&gt; = 2 = 0.2 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;000000000001&lt;/code&gt; = 1 = 0.1 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;000000000000&lt;/code&gt; = 0 = 0.0 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;111111111111&lt;/code&gt; = 4095 = -0.1 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;111111111110&lt;/code&gt; = 4094 = -0.2 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;111111111101&lt;/code&gt; = 4093 = -0.3 °C&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;111111111100&lt;/code&gt; = 4092 = -0.4 °C&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means this bit field supports values between -2048 °C and +2047 °C.&lt;/p&gt;

&lt;p&gt;Unsurprisingly, the receiver isn't impressed when I give it such extreme values as it displays "LL.L" for values below -99.9, and "HH.H" for values above 69.9.&lt;/p&gt;

&lt;p&gt;I did wonder why they limited the upper value to 69.9 specifically. Maybe the lack of accuracy isn't gauranteed that far from its tested calibration values or something, or to dissuade people from putting them in ovens as an oven thermometer. Perhaps they didn't think the sensor would ever see negative values ever to bother limiting it.&lt;/p&gt;

&lt;p&gt;It's fun that they mentioned it can work at +70 °C. They lied!&lt;/p&gt;

&lt;h3&gt;
  
  
  Humidity
&lt;/h3&gt;

&lt;p&gt;This one is simple enough. It's an 8-bit value. Unsigned, no operations needed. The receiver will limit this value on its display from 10% to 99% humidity. Nothing more, nothing less.&lt;/p&gt;

&lt;p&gt;Setting this value to extremes like 0 or 255 does nothing but make the display show 10% and 99% respectively.&lt;/p&gt;

&lt;p&gt;As mentioned at the beginning, the TX-2C transmitter I received with the temperature-only model was not made with a hygrometer. This did not change the protocol. The transmitter was sending the humidity value as a fixed value of ten (10) in decimal. This suggests the firmware reads the "sensor" input and clamps it between 10 and 99 before sending the signal out.&lt;/p&gt;

&lt;p&gt;Curious, as &lt;em&gt;some&lt;/em&gt; units ship without a hygrometer sensor, I removed these 8 bits as if they were truly optional, but unfortunately the receiver did not recognise the packet and did not trigger any update.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test mode
&lt;/h3&gt;

&lt;p&gt;Holding the "force transmit" button in on the transmitter while inserting batteries puts the device into some kind of test mode where it emits 100% duty cycle of packets non-stop. This basically becomes a radio jammer.&lt;/p&gt;

&lt;p&gt;The initial data it sends eight (8) times is this:&lt;br&gt;
&lt;code&gt;000000SL1001 00000000 0 1 00 001010111100 01111001&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first 12 bits again never change.&lt;/li&gt;
&lt;li&gt;The 8-bit pairing code is set to all zeros.&lt;/li&gt;
&lt;li&gt;Battery is always ok, even if they're nearly dead.&lt;/li&gt;
&lt;li&gt;Forced button bit is always set.&lt;/li&gt;
&lt;li&gt;Channel is always &lt;code&gt;00&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The temperature value is always 700 (or 70.0 °C, making the receiver show "HH.H").&lt;/li&gt;
&lt;li&gt;The humidity value is always 121%, making the receiver show "99%".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These frames are sent 8 times and then immediately change reflecting the real battery status, temperature, and humidity only. All other fields remain the same as bulleted above. Even though it's now constantly emitting packets of data, the actual sensor values do not update from frame-to-frame, or packet-to-packet. The values still only change every 50+ seconds as originally intended. &lt;/p&gt;

&lt;p&gt;The only use I can see for this behaviour is aiding manufacturing to make sure the units are emitting a signal quickly and correctly for more than 1 second. Accidentally holding that button while inserting the batteries is a fairly likely action and would drain the batteries quickly, interfere with other or identical devices on that frequency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before we finish...
&lt;/h3&gt;

&lt;p&gt;I decided to play with the bits near the beginning of the frames where it's &lt;code&gt;1001&lt;/code&gt; and changing these made no difference at all. The receiver seems to almost ignore these but it's noteworthy to say these are not part of the pairing code immediately after it. Perhaps this is a version number for the protocol used.&lt;/p&gt;

&lt;p&gt;The symbols on the end of the frame that I label &lt;code&gt;S0&lt;/code&gt;, the &lt;code&gt;S&lt;/code&gt; is always present but the &lt;code&gt;0&lt;/code&gt; seems to indicate a repeat frame is about to happen, kind of like a separator. The last frame out of the 8 omit this symbol.&lt;/p&gt;

&lt;p&gt;Now I can put these devices to rest and hopefully somebody found this useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other products
&lt;/h2&gt;

&lt;p&gt;They sell other products like the TP211B, TP280B, and TP260B claim to operate on 915 MHz (America) or 868 MHz (Europe) using Frequency Shift Keying (FSK) instead of OOK. Maybe it will be interesting to decode those one day.&lt;/p&gt;

</description>
      <category>sdr</category>
      <category>rf</category>
      <category>thermopro</category>
      <category>reverseengineering</category>
    </item>
  </channel>
</rss>
