Bedjet integration?

Should be this weekend

I’m certainly no professional, so aspects of it are probably janky, but it has been working well for me and I’m hoping it’s usable for others too and/or that someone else can run with it and improve it.

Just got a bit of cleanup and additional testing and then I’ll get it posted here.


Frustratingly my bedjet is the last smart device in my home which remains elusively out of reach. You’re awesome, looking forward to finally getting this looped into HA.

Do you have any idea if this will work on a managed instance of HA?

I guess I am not sure what you mean by ‘managed instance of HA’

I have this working currently in Supervised Home Assistant (Home Assistant OS) using the official Node-Red addon - but there’s no reason this couldn’t be ran on any Node-Red machine on the network as long as HA is configured to look at that.

It’s been working well for me, but isn’t clean enough to be published yet. I would hate to put something out there that could cause problems for someones HA instance or bedjet because of me. I’ve unfortunately become insanely busy the past two week, but still intend to clean it up and put it out there for whoever wants to use.

If you know node-red or want to learn it I would take a look at the github link I posted above - this was my first Node-Red project ever and I was able to manage so I would think someone who knows Node-Red (and gatt, which was also new for me) should be able to make this

Right, supervised, that’s what I meant :sweat_smile:

Thought it was worth mentioning I found this by /u/pjt-0620/ on reddit. Seems to be a step in the right direction GitHub - pjt0620/Home-Assistant-Bedjet: Bedjet Home Assistant Mqtt Integration

Great to see more integrations!

Found this the other day. Hopefully it’s added soon. Would be great to use a low-cost ESP32 that could easily do other tasks too (bed occupancy sensor, etc.).

1 Like

Yeah I haven’t posted any additional info on my nodered setup for it because it’s not really bullet proof. It works great most of the time but my RPi 3 that’s acting as the ‘ble hub’/nodered host has gotten into a fit a few times and required quite a bit of intervention to get working each time.
Problems with nodered interfacing with the Bluetooth chip pop up randomly

Nodered is great but these two other implementations seem much more robust

FYI I was able to get this working with esphome on an esp32. It looks like they are going to commit a bedjet header file in a future release. This is good news. The bad news is, it seams the bedjet can only talk to one device at a time, so I cannot use home assistant and the mobile app. I literally just got this working 5 minutes ago so I will have to do a lot more testing on this.


I’m the author of the esphome bedjet component linked above, which is still pending code review so has not merged yet. I’ve been using it for the last few months and it has been working great so far. I use automations linked with my sleep-tracking app’s MQTT support, to start warming the bed when my sleep tracking app sends its “get ready for bed soon” event, and when the app enters the “smart wakeup” period, it switches the BedJet from heat to cool, as an incentive to get up.

The bad news is, it seams the bedjet can only talk to one device at a time, so I cannot use home assistant and the mobile app.

This is true as a side effect of the way BLE GATT servers work, unfortunately. To allow an easy way to work around that, I added documentation specifically to call this out and to add a recommended workaround by adding a ble_client switch device, which allows you to enable/disable the BLE client in the esphome integration. That lets you turn off a switch that effectively disconnects the ESP32 from the BedJet, thus allowing the app to function normally. When you’re done with the app, you can close it and then toggle the switch back on, which will reconnect the ESP device.

For what it’s worth though, I tried to make sure that the esphome component can do most of what I need it to do, and therefore I no longer miss having the ability to use the app, because I haven’t had a need to open the app since I fixed a BLE notification bug that was causing major issues with connection stability. After fixing that, and setting up my automations the way I want, I do not miss having the app :slight_smile:

Would be great to use a low-cost ESP32 that could easily do other tasks too (bed occupancy sensor, etc.).

Something simple like an occupancy sensor might work ok. It’s worth pointing out though that the ESP32 is somewhat limited by flash size and memory. In my house, I have a single ESP32 that talks to 2 separate BedJets, and that works okay because it only has to include the bedjet component once and then sets up 2 connections with the single component.

But it starts to run into problems when you try to upload new firmware to the ESP, because of the fact that the BLE client is pretty resource intensive, especially while receiving rapid BLE notifications – the firmware times out mid-upload if 2 clients are connected at the same time.

I have a workaround for that which is also documented in the bedjet component docs at the link above, that suggests adding an esphome ota.on_begin automation that will disable the BedJet clients when a firmware upload begins. That has solved the ESP overloading issues for me when uploading the new firmware. I bring that up, because it highlights the limitations of the ESP devices, and while it may work with something that uses simple GPIO inputs like the occupancy sensor idea, anything heavier than that may not work properly and may cause intermittent crashes (for example, I don’t think that it would be possible to add MQTT support alongside the bedjet component on a single device, because MQTT is also “heavy”, and both MQTT and BLE client together may not fit on the flash device, let alone runtime resources necessary to accomplish both).


I’m curious to see if this happens to work with with my BedJet v2, or if the bluetooth commands are different for some reason.

Hopefully ESPHome accepts the PR soon! :slight_smile:


Before discovering that somebody had already done the bulk of the work to get the device working with ESPHome/HA, I did some basic reverse engineering of the android app.

The decompiled code is … messy … but there were several clear parts of the code where the BTLE data was interpreted/composed differently based on the hardware revision. The differences are not huge so it’s probable that the esphome component could be adjusted to work with V2 hardware as well.

I should add that the APK refers to a v1 and v2 but it’s not clear if the 2nd generation of hardware is classified as v2 or v1 as far as the communications are concerned.

I hope this means there is progress being made, I haven’t looked into it other than the email I got today.

Thank you for being a BedJetter!

We recently released an important firmware update for the BedJet 3 and encourage you to download it. This firmware release V1.20 (140) does not add any new functionality to your BedJet, but does include changes that will improve reliability of future firmware updates. Your BedJet will not lose any functionality if you choose to skip this update, but you could lose out on the opportunity to get future feature upgrades.

Please note that your BedJet will need to connect to a 2.4GHz WiFi network to complete this firmware update.

Has it ever updated? Mine doesn’t seem to ever complete the process… It keep showing on the remote but fails. How long did the update take on your device?

Hi @madcoder,

I wanted to say a big thank you to you for creating this!

I just set up the ESPHome integration yesterday and it works, more or less, perfectly. The BedJet accepts commands and responds right away but the HA front end seems to take a little while to catch up (usually between 10-30 seconds) however this is 100% not at issue for my use case. Simply being able to issue commands is amazing!

One thing I haven’t been able to figure out is how to set the clock on the BedJet via ESPHome/Home Assistant.

I was able to implement the firmware upgrade lambda button and BLE client switch, both of which seem to work fine, and I can see in the source code that there is a “send_local_time_()” function but I can’t seem to get that working.

I have set up

  - platform: homeassistant
    id: homeassistant_time

and I’m currently using “homeassistant_time” as the time source:

  - platform: bedjet
    id: climate_bedjet_1
    name: ${friendly_name}
    ble_client_id: ble_bedjet_1
    time_id: homeassistant_time

I’m not sure if the time-setting functionality is supposed to be automatic or not but it doesn’t seem to be working for me.

I tried making a lambda similar to the firmware upgrade one but it won’t compile and says that send_local_time_() is a “protected member function”.

I was just hoping you might be able to provide some guidance.

Thanks again for making this amazing ESPHome integration!


I believe what you have done is all that’s needed.

Was wondering the same thing and checked the time on the bedjet before installing the integration and it was a minute off. Now has the proper time!

Hi, glad it’s mostly working for you.

  1. The delay in updating is something I deal with as well. There’s a couple problems leading to this, the biggest one is that the esp32 doesn’t currently have a way to configure how frequently the BTLE notification gets triggered, which means by default it becomes a “fire hose” that receives new updates as quickly as possible, usually on the order of every 100-200ms.

You’d think that means updates should happen more often and you’d be right. But I intentionally throttle the updates back to HA, in order to avoid overwhelming either the esp32 or HA. So even though it attempts to send the status update to HA as soon as the bedjet acknowledges the command, because of this rapid stream of status updates across a different service, that recent command tends to get “reverted” quickly, that revert gets sent to HA, and then the rapid stream of status notifications changes as well, but by then the reverted status was already sent, and now it’s in its “throttle” period and won’t update with the latest status until the next polling period (30sec by default, but can be configured by setting the polling interval).

A better improvement would be to make it smarter about sending status updates caused by a recent command; something like: if we recently sent a temp change, wait until the next update is received that matches that temp, before sending the current status. Or similar for mode, etc. Right now it’s just a naive throttle.

  1. I’ve also recently seen issues with the clock set, which is odd because it worked for me for a long time before it merged. But I did also install the recent firmware upgrade about a month or so back (I’m on the beta/test firmware). So it’s possible something about that firmware has changed the clock sync.

Another possibility, which is something I see on my bedjet but not on my wife’s, is that mine has issues with connectivity: it seems to drop connection every 30min (almost to the second it seems), and sometimes it takes multiple reconnect attempts before it succeeds. It does always reconnect ok, in its own, so it doesn’t bother me. Just that I notice it flap every 30 min in the connection binary sensor. The clock is synced after connecting, so I wonder if that gets lost at times because of this connectivity stability.

It also isn’t clear if there’s a distinction between setting the time on the bedjet vs on the remote, and/or if setting it over Bluetooth will show the time change on the remote. I’ll have to do some testing to know for sure.

Feel free to open GitHub issues for both of these, and I’ll take a look.

1 Like

If anyone here is a developer it may be possible to get a direct integration by helping the company.

The clock update issue seems to be fixed after upgrading ESPHome to 2022.5.1 and reflashing the ESP32.

One thing I noticed regarding stability of the connection was that it seems very dependent upon what the ESP was being powered with.

When I powered it from my laptop it stayed connected indefinitely. When I powered it from random USB chargers, I got extremely varied results. I tried various chargers from other devices that I had accumulated over time; they all power their original devices just fine but the ESP connection was very flaky when using them.

I wound up using an old Nexus 6 charger and it is very stable now; only two momentary drops in the last 24 hours.

Looks like there was a change in dev that didn’t get updated here - I know it worked when I added it! :joy: I see that Jesse fixed it so looks like that’s been released now.

I’m going to go ahead and make some changes so it can work from a lambda (like what you tried to do, but now it’ll work because it’s public), and also a separate public method that would let you set the clock manually even without a time_id component.

As for the connection stability: that is interesting, though maybe not entirely unexpected. However, in my case I’m not sure if that would be what’s affecting me, because I use a single ESP32 to communicate with both BedJet devices (mine and my wife’s). My wife’s BedJet doesn’t have the 30-min connection flapping, but mine does. Even more strange: every now and then mine seems to stabilize for a couple hours at a time, but eventually goes back to the 30-min flapping (like clockwork).

The clock sync changes were merged tonight, so latest dev version will allow you to make a template button that syncs the clock to the time_id that’s configured.

Regarding this first issue of taking ~30 seconds for the HA device to reflect status changes, I’ve made some changes today that should not only address that (I see updates reflected in HA within 1-2 seconds now), but also opens the door to adding other domain components, such as a fan component if you prefer that entity type over the awkward climate/thermostat “fan mode” drop-down selector. And I have a few other ideas as well.

It’s a big change, and I’ve only been running it for a few hours now. I’ll have a better idea about stability after letting it run a while longer. If you want to try it out, you can use the “external_components” block to point to my PR #3522. It is a breaking change, requiring some minor changes in the yaml, but those are explained in the docs PR. If you do try it out, I recommend backing up your current config so that you can revert back to the current version if the PR gives you trouble.