Github Boards Devices Community Docs Blog

Creating devices in Home Assistant

Currently, I have 4 xiaomi mijia lywsd03mmc integrated using an esp32 running the development brach of openmqttgateway.

For each device, 5 sensors are created, but they are not tied together, they don’t create a device to tie them together and assign them to an area.

homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-tempc/config

{
   "stat_t":"home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
   "name":"LYWSD03MMC-tempc",
   "uniq_id":"A4C138C9BC21-LYWSD03MMC-tempc",
   "dev_cla":"temperature",
   "val_tpl":"{{ value_json.tempc | is_defined }}",
   "unit_of_meas":"C"
}

homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-tempf/config

{
  "stat_t": "home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
  "name": "LYWSD03MMC-tempf",
  "uniq_id": "A4C138C9BC21-LYWSD03MMC-tempf",
  "dev_cla": "temperature",
  "val_tpl": "{{ value_json.tempf | is_defined }}",
  "unit_of_meas": "F"
}

homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-hum/config

{
  "stat_t": "home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
  "name": "LYWSD03MMC-hum",
  "uniq_id": "A4C138C9BC21-LYWSD03MMC-hum",
  "dev_cla": "humidity",
  "val_tpl": "{{ value_json.hum | is_defined }}",
  "unit_of_meas": "%"
}

homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-batt/config

{
  "stat_t": "home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
  "name": "LYWSD03MMC-batt",
  "uniq_id": "A4C138C9BC21-LYWSD03MMC-batt",
  "dev_cla": "battery",
  "val_tpl": "{{ value_json.batt | is_defined }}",
  "unit_of_meas": "%"
}

homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-volt

{
  "stat_t": "home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
  "name": "LYWSD03MMC-volt",
  "uniq_id": "A4C138C9BC21-LYWSD03MMC-volt",
  "val_tpl": "{{ value_json.volt | is_defined }}",
  "unit_of_meas": "V"
}

I tried to change, in ZmqttDiscovery.ino

#  ifdef ZgatewayBT
void createDiscoveryFromList(char* mac, char* sensorList[][8], int sensorCount) {
  for (int i = 0; i < sensorCount; i++) {
    Log.trace(F("CreateDiscoverySensor %s" CR), sensorList[i][1]);
    String discovery_topic = String(subjectBTtoMQTT) + "/" + String(mac);
    String unique_id = String(mac) + "-" + sensorList[i][1];
    createDiscovery(sensorList[i][0],
                    (char*)discovery_topic.c_str(), sensorList[i][1], (char*)unique_id.c_str(),
                    will_Topic, sensorList[i][3], sensorList[i][4],
                    sensorList[i][5], sensorList[i][6], sensorList[i][7],
                    0, "", "", false, "");
  }
}
#  endif

to

#  ifdef ZgatewayBT
void createDiscoveryFromList(char* mac, char* sensorList[][8], int sensorCount) {
  for (int i = 0; i < sensorCount; i++) {
    Log.trace(F("CreateDiscoverySensor %s" CR), sensorList[i][1]);
    String discovery_topic = String(subjectBTtoMQTT) + "/" + String(mac);
    String unique_id = String(mac) + "-" + sensorList[i][1];
    createDiscovery(sensorList[i][0],
                    (char*)discovery_topic.c_str(), sensorList[i][1], (char*)unique_id.c_str(),
                    will_Topic, sensorList[i][3], sensorList[i][4],
                    sensorList[i][5], sensorList[i][6], sensorList[i][7],
                    0, "", "", true, "");
  }
}
#  endif

But this has not the desired effect, I end up with something like

homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-tempc/config

{
   "stat_t":"home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
   "name":"LYWSD03MMC-tempc",
   "uniq_id":"A4C138C9BC21-LYWSD03MMC-tempc",
   "dev_cla":"temperature",
   "val_tpl":"{{ value_json.tempc | is_defined }}",
   "unit_of_meas":"C"
   "device": {
    "name": "OpenMQTTGateway_ESP32_BLE",
    "manufacturer": "OMG_community",
    "sw_version": "version_tag",
    "identifiers": [
      "4C11AE74F584"
    ]
  }
}

What I want to achieve, is to end up with something like this :
homeassistant/sensor/A4C138C9BC21-LYWSD03MMC-tempc/config

{
   "stat_t":"home/OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138C9BC21",
   "name":"LYWSD03MMC-tempc",
   "uniq_id":"A4C138C9BC21-LYWSD03MMC-tempc",
   "dev_cla":"temperature",
   "val_tpl":"{{ value_json.tempc | is_defined }}",
   "unit_of_meas":"C"
   "device": {
    "name": "LYWSD03MMC",
    "manufacturer": "OMG_community",
    "identifiers": [
      "A4C138C9BC21"
    ]
  }
}

and same device block for all 5 sensors for the same LYWSD03MMC

So I end up with something like this in HA

Got it. My changed function :

void createDiscovery(char* sensor_type,
                     char* st_topic, char* s_name, char* unique_id,
                     char* availability_topic, char* device_class, char* value_template,
                     char* payload_on, char* payload_off, char* unit_of_meas,
                     int off_delay,
                     char* payload_available, char* payload_not_avalaible, bool child_device, char* cmd_topic) {
  const int JSON_MSG_CALC_BUFFER = JSON_OBJECT_SIZE(14) + JSON_OBJECT_SIZE(5) + JSON_ARRAY_SIZE(1);
  StaticJsonBuffer<JSON_MSG_CALC_BUFFER> jsonBuffer;
  JsonObject& sensor = jsonBuffer.createObject();

  char state_topic[mqtt_topic_max_size];
  strcpy(state_topic, mqtt_topic);
  strcat(state_topic, st_topic);
  sensor.set("stat_t", state_topic); //state_topic

  sensor.set("name", s_name); //name
  sensor.set("uniq_id", unique_id); //unique_id
  if (device_class[0])
    sensor.set("dev_cla", device_class); //device_class
  if (value_template[0])
    sensor.set("val_tpl", value_template); //value_template
  if (payload_on[0])
    sensor.set("pl_on", payload_on); // payload_on
  if (payload_off[0])
    sensor.set("pl_off", payload_off); //payload_off
  if (unit_of_meas[0])
    sensor.set("unit_of_meas", unit_of_meas); //unit_of_measurement*/
  if (off_delay != 0)
    sensor.set("off_delay", off_delay); //off_delay
  if (payload_available[0])
    sensor.set("pl_avail", payload_available); // payload_on
  if (payload_not_avalaible[0])
    sensor.set("pl_not_avail", payload_not_avalaible); //payload_off

  if (cmd_topic[0]) {
    char command_topic[mqtt_topic_max_size];
    strcpy(command_topic, mqtt_topic);
    strcat(command_topic, cmd_topic);
    sensor.set("cmd_t", command_topic); //command_topic
  }

  if (child_device) {
    StaticJsonBuffer<JSON_MSG_BUFFER> jsonDeviceBuffer;
    JsonObject& device = jsonDeviceBuffer.createObject();
    device.set("name", gateway_name);
    device.set("manufacturer", DEVICEMANUFACTURER);
    device.set("sw_version", OMG_VERSION);
    JsonArray& identifiers = device.createNestedArray("identifiers");
    identifiers.add(getMacAddress());
    sensor.set("device", device); //device sensor is connected to
  }
  else {
    char deviceid[13];
    char devicename[40];
    int index = 0;
    memcpy(deviceid, &unique_id[0], 12 );    
    deviceid[12]= '\0';
    index = strcspn (s_name,"-");
    memcpy(devicename, &s_name[0], index );    
    devicename[index]= '\0';
    StaticJsonBuffer<JSON_MSG_BUFFER> jsonDeviceBuffer;
    JsonObject& device = jsonDeviceBuffer.createObject();
    device.set("name", devicename);
    device.set("model", devicename);
    device.set("manufacturer", DEVICEMANUFACTURER);
    JsonArray& identifiers = device.createNestedArray("identifiers");
    identifiers.add(deviceid);
    sensor.set("device", device); //device sensor is connected to
  }


  String topic = String(discovery_Topic) + "/" + String(sensor_type) + "/" + String(unique_id) + "/config";
  pub_custom_topic((char*)topic.c_str(), sensor, true);
}

1 Like

Very good! I have 10 sensors and I want apply it on my Hass; have you solved all the problem or have you any other issues?

it is only tested with my 4 LYWSD03MMC’s, but it should work with all BLE sensors.