[HOW TO] Advanced Virtual Device for Bluetti devices (need an ESP32)

Hi, i created a method for interfacing a Bluetti power station with Homey.
You need an esp32 with a firmware can bridge bluetooth data to json data
You can use it for reading value from your power station and populate a virtual device created with Device Capabilities app.
I have tested it with an bluetti AC200Max and a battery pack
Actually it only read some info.

Prerequisites:

Step 1: Create a homeyscript for get the power station data (example bluetti_bridge.js)

const b_ip = 'YOUR_ESP32_BRIDGE_IP';
const b_baseurl = 'http://'+ b_ip + '/getData';

function toFixed(num) {
  return Math.trunc((num / 1000) * 100) / 100;    
}

function toFixed2(num) {
  return Math.trunc((num * 100) / 100);    
}

let bluetti = { 'solar_power': '-1', 'home_power': '-1', 'grid_power': '-1', 'battery': '-1', 'ac': 0, 'dc': 0, 'batteries': { 'main': '-1', 'one': '-1', 'two': '-1'} };
try {
  const res = await fetch(b_baseurl);
  if (res.ok) {
    // Get the body JSON
    const data = await res.json();
    //log(data)
    if (data != null) {      
      if (data['dc_input_power'] != null) bluetti.solar_power = toFixed(data['dc_input_power']);
      if (data['ac_output_power'] != null) bluetti.home_power = toFixed2(data['ac_output_power']);
      if (data['ac_input_power'] != null) bluetti.grid_power = toFixed2(data['ac_input_power']);      
      if (data['total_battery_percent'] != null) bluetti.battery = toFixed2(data['total_battery_percent']);
      if (data['pack_battery_percent'] != null) {
        bluetti.batteries.main = toFixed2(data['pack_battery_percent']);
        bluetti.batteries.one = toFixed2((data['total_battery_percent']*2) - data['pack_battery_percent']);
      }
      if (data['ac_output_on'] != null) bluetti.ac = toFixed2(data['ac_output_on']);
      if (data['dc_output_on'] != null) bluetti.dc = toFixed2(data['dc_output_on']);      
    }
  }
} catch (err) {
  bluetti = { 'solar_power': 0, 'home_power': 0, 'grid_power': 0, 'battery': 0, 'ac': 0, 'dc': 0 };
}

if (bluetti.solar_power != '-1') await tag('bluetti_data_solar_power', bluetti.solar_power);
if (bluetti.home_power != '-1') await tag('bluetti_data_home_power', bluetti.home_power);
if (bluetti.grid_power != '-1') await tag('bluetti_data_grid_power', bluetti.grid_power);
if (bluetti.battery_percent != '-1') await tag('bluetti_data_battery', bluetti.battery);
if (bluetti.batteries.main != '-1') await tag('bluetti_data_battery_main', bluetti.batteries.main);
if (bluetti.batteries.one != '-1') await tag('bluetti_data_battery_one', bluetti.batteries.one);
if (bluetti.ac != '-1') await tag('bluetti_data_ac', bluetti.ac);
if (bluetti.dc != '-1') await tag('bluetti_data_dc', bluetti.dc);
     
//log(bluetti);
return true;

Step 2: Create a Virtual Device for your Bluetti power station

  • With app or my.homey.com create a new “Device capabilities” device.

Step 3: Configuring Device Settings

  • Define the capabilities your virtual device will have, you could also import this sample [TEF] String
[tef:AVD:"H4sIAAAAAAACA42Wa4+qOhSG/8qkyfk0TkBuosn5IPUy6iDe0Tk52SmlXBQotkXRnf3fd9wzszFz5wuhq2ut931YTfoT+OQQYzLANAMtcK/xQfvpgW1ttVi4t9i2YLNZx+FiX991zpNbn7lcdOolGpkY0xSvp/mgMfA3kKcS086LEdyPR3yx2Emyaeuaqgo1Gxdi8rjWbCF1lh3Zlg6LM4kSSTQ8Km/UyYjXnU2b3XZxfZKq5vjBVtDy0ZQybT04mIqBvOT2YZPsXBfOcNnYTOPeFutnb6Iz/fGQKMGpPJ7PnVk8ZNN+Lk2aXrHPqL+TIjfZl3lwvymDvmC3cnEaiYaiRwZ74CtnIyXQPm6znaUk/mh0gshx+9NuOC8jK5QeYne6WG17/vp+g6zwNJQhc8MQzps89DoK4ZPBIO8Xkb9coul0Ex1nqWuPdr1whuyhFdUtaG/scGjdd8OyHZEhNPcdG5aRs19yZDu79pL45d6y5uwRKtRYzvRYt/bY2ONuv2Mu4q1yEsnQ7piRMiGNZQgxa670AEqPinMw1qywH4UISl8ssROlw+nAkg6lMIvC3Y23hhLVh2x5srLpcGVC6EF3uCn3Wt73osl6L/f7W9eV5+f7+MiSATxiIejQ9aL7pi3FltdNVvMZamYhgpSXiN+64V5Otz2NFF2LyI7ebRvJobNydrP+mo52abi19mqTqqEkH/Xdw9R2zLYyDvIGT3e5OqX2qpPt6ttiXEpr7p9T1JRhb3JO5054YtvTwFHWh/H2oKUTL5Do2O15dcPcdNrt9r+gBnDBBU0vM8pB6+evGqAsDuMMJQMftEDTV0gT1dW7wGvgO82oN+9Mlch3SJYD3fBwoPsNUAOcCBFn4aUCIBlh4enHASUF+XEpK1AmQCsrkqQGsiL1CHOCBSlFLyaJz0FLrpbHf94vAaMKWJQmBGXvpFiFEPRvoF4FIEoJQ1cZOOGgBaiICAMv2+pjlBLQAhCxGKMbH90wIkgVnpMcMSQIRDny4iQWMeGgFaCEk2pPRI/tS+mUIF4w8iOnx+sWkBEkSC+hR4jYRYtgRZW9zGJxSXarhA7BcYqSazvPRRYofN39KTDIeBxG4rU2J3iI+TXonHLxBBm0dOPp+/KjVU1rNBs1IGge48uCYRqNv/yVZ0oWEoKwGN0IKlBSYVK+gUl5g8n7U+1UVXlB8U+19JFt5bXta6bKp8SVd/CqzwYnjPrFOaYZueE0QayyqH7DovrGIi4YI5moqrzX++0EqJ8aUD+Con4GRZ2RICFYgBa4HFiBRMFfpv9vY+3lONCMFym9wYijKvgNBNqXCLRPvWlvYWjvMNM+QqB9hkB/PcY5izMc59ejrH/DpP7lKOtvR1l/x4bxWhAnmGY+YnFF3fiGIONLQcZbQcaVoF+157vKs6A2VGTZRiWoAQRa//3/6zccbzq6zAgAAA==":/tef]

Step 4: Populate the virtual device with a flow

This is a implementation sample, you can suggest optimization or fix :slight_smile:

2 Likes