I have a Petrainer PET998DRU shock collar (similar to this one) that got partially chewed up by the dog it is supposed to train. I salvaged it to the point where I have the following buttons:

  • Mode (to select light, beep, vibrate, and zap
  • Activate (to send appropriate stimulation)
  • Up arrow (to increase the amount of stim)

The display does not work so I don't know what the setting (which stim and how much) is on other than trial and error.

I have followed the method on here: http://brettleaver.com/collar/ to get as far as I have gotten but the protocol differs on this model and I have only been able to figure out the device ID and the stim type (I think). I can replay the packets on a separate 433Mhz transmitter and the collar responds appropriately but I want to figure out the whole packet. The amount of stim is what I need helping decoding.

Logic for beep Image for beep (no duration is encoded by design)

I decoded this as 0xDF 7E DE ED 7F D6 AB If this is wrong, then please let me know because it may give me a clue as to why I can't figure out the rest.

Logic for zap Image for zap (unknown duration)

I decoded this as 0x‭DF DE DE ED 6F 7A AA C0‬. The last bits to finish up the last octet are assumed to be logic 0's. Maybe this assumption is wrong though.

I decoded the other packets similarly but I won't post all the images.

EDIT: I have since gotten captures of vibrates and zaps where I know the duration is 0.

  • Light: 0xDE FE DE ED 7F D5 AB
  • Beep: 0xDF 7E DE ED 7F D6 AB
  • Zap: 0x‭DF DE DE ED 7F EA AB‬
  • Vibrate 0x‭DF BE DE ED 7F DA AB

All the packets except the Light start out with 0XDF. The next position (7, F, D, or B) seems to determine stim type. The next 5 are always0xE DE ED so that seems to determine the device ID. All the characters after that are encoding the duration of the zap or buzz and then something to do with a checksum of some sort.

Here is what I got for the buzz stim in sequential order. After recording each one, I incremented by one and then sent the command again:

  • 0x‭DF BE DE ED 7F AD 55 80
  • 0x‭DF BE DE ED 7F 6D 55 80
  • 0x‭DF BE DE ED 7F 56 AA C0
  • 0x‭DF BE DE ED 7E ED 55 80
  • 0x‭DF BE DE ED 7E D6 AA C0 ...

An interesting thing I found is that one of the following patterns are always present but I can't figure out the significance:

  • 0x__ _B 55 60
  • 0x__ _D 55 80
  • 0x__ _6 AA C0
  • 0x__ _5 AA B0

EDIT: Another interesting thing to note is that there is never 2 consecutive zeros.

Assuming I haven't made a huge mistake from the beginning (this is my first attempt at reverse engineering something), does anyone see an obvious encoding scheme or checksum that is being used?

My end goal is to code up a new 433MHz transmitter and make it controllable with a yet to be made mobile app.

  • Hardware reverse engineering may help.
    – Biswapriyo
    Commented Oct 20, 2018 at 13:37
  • Meaning, analyze the transmitter hardware and do a dump of its firmware?
    – dreed75
    Commented Oct 20, 2018 at 13:49
  • This sounds like a lot of effort in comparison with buying a new one. :)
    – user202729
    Commented Oct 22, 2018 at 10:30
  • By the way, can you explain how the thing is supposed to work? Not everyone knows what a pet trainer is. (so there is a part that receives the signal, and another part which is like a remote controller, that has some buttons broken because of the dog, right?)
    – user202729
    Commented Oct 22, 2018 at 10:31
  • Also: What are you trying to do? ("simulate" broken buttons? If so which one?)
    – user202729
    Commented Oct 22, 2018 at 10:32

1 Answer 1



Consider a "gap" to be a "low" interval between two consecutive "high" interval, ignoring the first longest one. Then, a bit 1 corresponds to a long gap, and a bit 0 corresponds to a short gap.

Therefore, the messages decoded that way are:

88 14 4b 00 ee   : Light
84 14 4b 00 de   : Beep
81 14 4b 00 7e   : Zap
82 14 4b 00 be   : Vibrate
82 14 4b 01 be   : Buzz stim in sequential order
82 14 4b 02 be
82 14 4b 03 be
82 14 4b 04 be
82 14 4b 05 be
82 14 4b 06 be
82 14 4b 07 be
82 14 4b 08 be

That follows the exact same pattern as described at http://brettleaver.com/collar/, except that the remote UID is 14 4b instead of 20 89.

(quoting the link above:

Now we can easily decode what the remote is sending! After changing the settings several times and looking at how it changes the transmission, it became clear what the signal represented.

81 20 89 32 7e
This will be set to 8 if the remote is on channel 1
This will be set to f if the remote is on channel 2

81 20 89 32 7e
This will be set to 1 when the remote is requesting a shock
This will be set to 2 when the remote is requesting a vibration
This will be set to 4 when the remote is requesting a beep
This will be set to 8 when the remote is requesting an LED flash

81 20 89 32 7e
These bytes represent the UID of the remote, and never change.

81 20 89 32 7e
This byte represents the intensity of the vibration/shock.
The collar will ignore anything above 100

81 20 89 32 7e
This will be set to 7 when the remote is requesting a shock
This will be set to B when the remote is requesting a vibration
This will be set to D when the remote is requesting a beep
This will be set to E when the remote is requesting an LED flash

81 20 89 32 7e
This will be set to E if the remote is on channel 1
This will be set to 0 if the remote is on channel 2

81 20 89 32 7e
This last byte is equal to the first byte, but with its bits reversed and inverted. I think it’s some kind of error checking mechanism, as the collar will ignore all transmissions where this isn’t the case.



Consider the signal in binary:


Note how the bold italic part appear in all of the sequences, and not in a fixed place? That leads me to suspect that the message has a variable length, and the trailing zeroes doesn't matter.

The common prefix of all the messages is 11011111101111101101111011101101011111. We will cut out this part, but leave a 1 in the message -- the reason will be apparent later.

The remaining part is:


Note that this is supposed to be (a part of) an increasing, consecutive number sequence.

From OP's observation (there are no two consecutive zeroes), and note that there are 3 pairs in the data above where the latter one is the former one with a 0 appended, I guess that a 0 is encoded as a 10 and a 1 is encoded as a 1 (or vice versa).

Replacing 10 with 1 gives:


Looks good enough. This counts in decreasing order, so we have to negate the bits (0 is encoded as 1, 1 is encoded as 10).

It's obvious that the bits come in decreasing significance (most significant bit first). Because the value represented is from 1 to 100, the 3 previous bits are also a part of the value.

I also suspect that

is only a start-of-transmission mark and does not contribute to the data, because it's larger than all the others.

  • Thanks for that. Do you really think they designed it that complex? Does this encoding somehow make it a more robust transmission? I'll code up a converter where I can give it an input of an actual number and it will output the above encoding. Then I'll try other numbers from 0-100 and see if the collar responds.
    – dreed75
    Commented Oct 25, 2018 at 22:35
  • Great clue user202729! I went ahead and decoded the entire bitstream following your example (1=0, 10=1) and also ignored that first bit. The values I got are exactly the same as the values at brettleaver.com/collar except my device ID is 14 4B. If you want to edit your answer to clear that up, I'll accept your answer. Any idea why they encoded it that way? Maybe it's just to make reverse engineering difficult :).
    – dreed75
    Commented Oct 26, 2018 at 2:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.