SmartView2 In Home Display MQTT Integration

I came across tekelectron’s project, where he successfully managed to read data from the USB port of his SmartView2 in home display. I have the same IHD myself, so I thought I would give this a go. This project is the result of what I found.

The USB port on the rear of the SmartView2 in home display is just a standard USB micro connector. This port is used for charging the device, as it has an internal battery, though mine is left plugged in all the time. Connecting the device to a PC produces the “USB Device Not Recognized” error, so it is obviously not intended to work as a USB device.

According to tekelectron, the USB port produces serial data, and a bit of probing with my oscilloscope proved this to be true. I couldn’t decipher much from this, so I went ahead and used my Arduino Mega to read the data, and simply send this to my PC to display it in the serial console of the IDE. This is the program I used.

const int BUFFER_SIZE = 385;
byte buf[BUFFER_SIZE];
int i;

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
}

void loop() {
  // wait for incoming data
  while (Serial1.available() == 0) {
    // do nothing
  }

  // read the incoming bytes:
  int rlen = Serial1.readBytes(buf, BUFFER_SIZE);

  // prints the received data
  for(i = 0; i < rlen; i++){
    Serial.print(buf[i], HEX);
    Serial.print(",");
  }
  Serial.print("\n");
}

The baud rate was based on tekelectron’s initial finding, and worked perfectly. I have since found that the buffer size is not important.

This is a cleaned up sample of what I captured, as a simple text file.

The Arduino code places the comma between each byte, so it can be read easily as a CSV file. I used Putty to log the data, and then used Excel to add leading zeros to any single digits (0 – F). This makes the data much easier to read.

Next was the more difficult part. Having the data in Excel meant that I could filter it, and look for patterns and repetitions. Some of the data translates into text, as it is simply ASCII values. In the snip above, several of the lines begin with 72, 61. The section up to 0A translates as below.

72 61 6E 20 43 43 35 31 3A 31 3A 37 30 32 20 31 32 0A = ran CC51:1:702 12

This really doesn’t mean anything to me at all.

Using asciitable.com, it became clearer which sections were text, and which sections might contain data. What I found is that the data sections begin with F1, and end with F2. I decided to ignore the ASCII sections, and focus on the data between the F1 start points, and the F2 end points. I wrote a bit of script to filter this out for me, and then did several hours of recording over a couple of days.

Using the filter function of Excel, I was able to fish out each of the distinct packets of data from the log. With only one packet at a time showing, it was easy to see which bytes changed, and which stayed the same. The bytes that changed could possibly relate to some piece of information that my meters had read. Noting that tekelectron had read the bytes as little endian, I followed the same, and converted the most common packet’s changing bytes to decimal. Sure enough, this matched the current electricity wattage!

Below is a complete list of the packets I picked out, and what I have discovered about them (underlined bytes). It is a little bit pieced together sorry, as my findings didn’t come all at once, and I took data from several days. The packets are in the order they are transmitted. They are repeated in order, with the current electricity wattage being transmitted the most frequently. I have removed the F1 and F2 markers.

Transmitted approximately once every 8 seconds

04 01 02 07 07 02 00 30 00 00 04 00 2A DB 00 00
Current electricity wattage (W) (may be 3 bytes)

00 05 B7 24 ← This packet is transmitted after every packet, and has 2 bytes that change.

Transmitted once after 5 repeats of above

04 00 02 07 00 00 00 25 74 7D 1B 00 00 00 01 0C 00 22 E6 46 00 14 00 00 30 02 00 02 00 18 02
Gas meter reading (m³) Daily gas used

00 05 B2 17

04 00 05 07 1C 05 00 25 86 79 02 00 00 00 00 00 00 19 94 0C
Gas cost today (£)

00 05 B3 1A

04 01 05 07 1C 05 00 25 82 49 02 00 00 00 00 00 00 19 94 0C
Electricity cost today (£)

00 05 B4 1C

04 01 02 07 00 00 00 25 03 BD 68 00 00 00 01 04 00 22 C3 0D 00 14 00 00 30 02 00 02 00 18 00
Electricity meter reading (kWh) Daily electricity used

00 05 B3 1A

05 00 02 07 08 8B

00 05 B4 1C

04 01 02 07 07 02 00 30 00 00 04 00 2A DB 00 00
Current electricity wattage (W)

00 05 B4 1C

01 01 50 89 62 2D 0B 00 00 00

03 01 02 07 07 00 00 50 89 62 2D 00 08 07 01 00 0B 00 00

00 05 B3 1A ← I removed this packet from the section below.

Transmitted once every 29 repeats of all above

04 00 02 07 04 0A 00 18 50 00 0A 00 23 AC 9C 36 00

04 00 02 07 03 0C 00 22 DF 46 00 32 0C 00 22 CF 4E 02 42 0C 00 23 36 28 0E 00
Gas used yesterday (kWh)

04 00 05 07 30 05 00 25 71 2B 02 00 00 00 40 05 00 25 EF 83 3D 00 00 00

04 01 08 07 01 01 00 41 0E 4F 63 74 6F 70 75 73 20 45 6E 65 72 67 79 02 01 00 41 0D 30 38 30 38 20 31 36 34 20 31 30 38 38
String “Octopus Energy” 0808 164 1088

04 01 05 07 30 05 00 25 6A 50 02 00 00 00 40 05 00 25 E3 45 33 00 00 00

04 01 02 07 04 0A 00 18 50 00 0A 00 23 CB C1 2E 00

04 01 02 07 03 04 00 22 80 16 00 32 04 00 22 0F 81 00 42 04 00 23 EF 1D 02 00
Electricity used yesterday (kWh)

04 00 02 07 30 0C 00 22 66 3C 00 40 0C 00 23 81 37 07 00 11 03 00 41 04 30 30 30 30

04 00 05 07 1E 05 00 25 24 79 02 00 00 00 32 05 00 25 6B 0D 14 00 00 00 42 05 00 25 A4 CE 75 00 00 00

04 01 08 07 00 04 00 23 88 13 00 00 01 04 00 23 20 4E 00 00

04 01 05 07 1E 05 00 25 24 42 03 00 00 00 32 05 00 25 13 A6 13 00 00 00 42 05 00 25 C6 A7 53 00 00 00

04 01 02 07 30 04 00 22 01 0E 00 40 04 00 23 C5 4B 01 00 11 03 00 41 40 30 30 30 30

I have highlighted the parts that change, and what they match up to on the SmartView2 IHD. What I have discovered is that the second byte of the packet starts with 01 for an electricity reading, and 00 for a gas reading. Each packet with an electricity reading has a matching packet for the same reading of the gas (I think). There isn’t a packet for the current wattage of the gas though, and on the IHD, this only updates every half hour or so. In some of the packets, only two bytes ever change, and not three. If these packets have a matching packet from the other energy source reading, and three bytes change in this, then I have highlighted the same three bytes in these packets. This is probably because more energy was drawn from one energy source, compared to the other. There is something not right with the gas and electricity used yesterday. I thought I had this sussed at one time. The gas matches up, but the electricity doesn’t. I have taken the reading out of my project for now.

How does this relate to Home Assistant? Below is the code that I have written (taking snips from tekelectron and others), which reads the data packets, and sends the readings to a webpage using AJAX. I have switched over to using an ESP8266 for this, on an ESP-01 module. Only the current electricity wattage is sent to Home Assistant at the moment, using MQTT. The code does work well, but I have discovered that there are errors sent in the packets (the occasional extra value sent). Either that, or I drew 30,000 watts of electricity at one point during the day! I don’t have a secret time travelling DeLorean stashed away.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h> //MQTT messaging
#include "Webpage.h"  //Wepage containing readings

const char* ssid = "Your SSID Here";
const char* password = "Your SSID Password Here";
const char* mqtt_server = "MQTT Broker IP";
const char* mqtt_user = "MQTT User";
const char* mqtt_password = "MQTT Password";

char msg1[10];

ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);

String XMLData;
byte pktStart[1], pktEnd[1], packet[42];
long int eMeterRead1, eMeterRead2, eMeterRead3, eMeterRead4, gMeterRead1, gMeterRead2, gMeterRead3;
String seMeterRead1 = "0", seMeterRead2 = "0", seMeterRead3 = "0", seMeterRead4 = "0", sgMeterRead1 = "0", sgMeterRead2 = "0", sgMeterRead3 = "0";
String sPacket;
int header;
int i, j, bufLen;

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("MQTT connecting...");
    // Create a client ID
    String clientId = "ESP8266-Client-";
    clientId += String(WiFi.macAddress());
    // Attempt to connect
    if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
      Serial.print("Connected.");
      Serial.println();
      // Once connected, publish an announcement...
      client.publish("energy/meterread", "Meter Readings.");
    } else {
      Serial.print("Failed. Retrying in 5 seconds...");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  // Configure serial ports
  Serial.begin(115200);
  Serial.setTimeout(4000);
  delay(10);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
   
  WiFi.begin(ssid, password);
   
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
   
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  server.on("/", SendWebsite);
  server.on("/emeter", SendXML);

  // Start the server
  server.begin();
  Serial.println("Server started");

  Serial.println("Connecting to MQTT server");
  client.setServer(mqtt_server, 1883);

}

void loop() {

  // Reconnect to MQTT if not connected
  if (!client.connected()){
    reconnect();
  }
  client.loop();

  // Wait for something in the serial buffer
  while(Serial.available() > 0){
    i = 0;
    // Look for F1 start indicator
    Serial.readBytes(pktStart, 1);
    if(pktStart[0] == 0xF1){
      // Read the next byte of the packet until F2 is received
      Serial.readBytes(pktEnd, 1);
      while(pktEnd[0] != 0xF2){
        packet[i] = pktEnd[0];
        i++;
        Serial.readBytes(pktEnd, 1);
      }
    }

    // Search packet if it was greater than two bytes
    if(i > 2){
      sPacket = "";
      for(i = 0; i < sizeof(packet); i++) {
        sPacket = sPacket + String(packet[i], HEX) + ",";
      }
      header = packet[0] + packet[1] + packet[2] + packet[3] + packet[4];

      switch(header){

        case 0x0D:
          Serial.print("G Meter Reading: ");
          gMeterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sgMeterRead1 = gMeterRead1;
          Serial.print(sgMeterRead1);
          Serial.print(" m³");
          Serial.print(" " + sPacket + "\n");
          break;
        
        case 0x2C:
          Serial.print("G Cost Today: ");
          gMeterRead2 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sgMeterRead2 = gMeterRead2;
          Serial.print(sgMeterRead2);
          Serial.print(" " + sPacket + "\n");
          break;

        case 0x10:
          Serial.print("Gas Used Yesterday: ");
          gMeterRead3 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sgMeterRead3 = gMeterRead3;
          Serial.print(sgMeterRead3);
          Serial.print(" kWh");
          Serial.print(" " + sPacket + "\n");
          break;

        case 0x15:
          Serial.print("Current Wattage: ");
          eMeterRead1 = (packet[14] << 8) + packet[13];
          seMeterRead1 = eMeterRead1;
          sprintf(msg1, "%u", eMeterRead1);
          client.publish("energy/meterread", msg1);
          Serial.print(seMeterRead1);
          Serial.print(" Watts");
          Serial.print(" " + sPacket + "\n");
          break;
        
        case 0x0E:
          Serial.print("E Meter Reading: ");
          eMeterRead4 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          seMeterRead4 = eMeterRead4;
          Serial.print(seMeterRead4);
          Serial.print(" kWh");
          Serial.print(" " + sPacket + "\n");
          break;

        case 0x2D:
          Serial.print("E Cost Today: ");
          eMeterRead2 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          seMeterRead2 = eMeterRead2;
          Serial.print(seMeterRead2);
          Serial.print(" " + sPacket + "\n");
          break;

        //case 0x11:
        //  Serial.print("Electric Used Yesterday: ");
        //  eMeterRead3 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
        //  seMeterRead3 = eMeterRead3;
        //  Serial.print(seMeterRead3);
        //  Serial.print(" kWh");
        //  Serial.print(" " + sPacket + "\n");
        //  break;

        default:
          break;

      }
    }
  }
  server.handleClient();
}

void SendWebsite() {

  server.send(200, "text/html", PAGE_MAIN);

}

void SendXML() {

  XMLData = "<?xml version=\'1.0\'?>";
  XMLData += "<readings>";
  XMLData += "<emeter>" + seMeterRead4 + "</emeter>";
  XMLData += "<ewattage>" + seMeterRead1 + "</ewattage>";
  XMLData += "<edcost>" + seMeterRead2 + "</edcost>";
  XMLData += "<eyesterday>" + seMeterRead3 + "</eyesterday>";
  XMLData += "<gmeter>" + sgMeterRead1 + "</gmeter>";
  //XMLData += "<gwattage>1234</gwattage>";
  XMLData += "<gdcost>" + sgMeterRead2 + "</gdcost>";
  XMLData += "<gyesterday>" + sgMeterRead3 + "</gyesterday>";
  XMLData += "</readings>";

  server.send(200, "text/xml", XMLData);

}

The code for webpage.h is below

const char PAGE_MAIN[] PROGMEM = R"=====(

<!DOCTYPE HTML>
<html lang="en" class="js-focus-visible">

<title>SmartView2 Readings</title>

<body onload="loadDoc()">

    <script type = "text/javascript">
        function loadDoc() {
          const xhttp = new XMLHttpRequest();
          xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
              updateReadings(this);
            }
          }
          xhttp.open("GET", "/emeter");
          xhttp.send();
          setTimeout(loadDoc, 200);
        }

        function updateReadings(xml) {
          var xmlDoc = xml.responseXML;
          var x = xmlDoc.getElementsByTagName("readings");
          document.getElementById("emeter").innerHTML = x[0].getElementsByTagName("emeter")[0].childNodes[0].nodeValue;
          document.getElementById("ewattage").innerHTML = x[0].getElementsByTagName("ewattage")[0].childNodes[0].nodeValue;
          document.getElementById("edcost").innerHTML = x[0].getElementsByTagName("edcost")[0].childNodes[0].nodeValue;
          document.getElementById("eyesterday").innerHTML = x[0].getElementsByTagName("eyesterday")[0].childNodes[0].nodeValue;
          document.getElementById("gmeter").innerHTML = x[0].getElementsByTagName("gmeter")[0].childNodes[0].nodeValue;
          document.getElementById("gdcost").innerHTML = x[0].getElementsByTagName("gdcost")[0].childNodes[0].nodeValue;
          document.getElementById("gyesterday").innerHTML = x[0].getElementsByTagName("gyesterday")[0].childNodes[0].nodeValue;
        }
    </script>

    <div>
        <h2>Electricity</h2>
        <p></p>
        <p>Current Meter Reading (kWh):<div id="emeter">0</div></p>
        <p>Current Wattage (W):<div id="ewattage">0</div></p>
        <p>Current Cost Today (&pound;):<div id="edcost">0</div></p>
        <p>Use Yesterday (kWh):<div id="eyesterday">0</div></p>
    </div>
    <div>
        <h2>Gas</h2>
        <p></p>
        <p>Current Meter Reading (m&#179;):<div id="gmeter">0</div></p>
        <!--<p>Current Wattage (W):<div id="gwattage">0</div></p>-->
        <p>Current Cost Today (&pound;):<div id="gdcost">0</div></p>
        <p>Use Yesterday (kWh):<div id="gyesterday">0</div></p>
    </div>

</body>
</html>

)=====";

This is a work in process, and needs some error checking adding. Maybe you will be able to add your insight into the project, and better decode the packets. Maybe they already have some kind of parity check in them, which just needs to be decoded. If you have a SmartView2, and would like to give this a go, then let me know how this turns out, and the results you get. Other IHDs may give out similar data too. Apart from tekelectron’s post, I can’t find any other write up of anybody trying this with their IHD. It goes without saying that all of the above has been done using my knowledge of electronics and coding. Please don’t hold me responsible if it doesn’t work out the same for you in your trials, or anything stops working.

Thanks for reading.

1 Like

After some debugging and edits, I now have a complete working code for the ESP8266, including MQTT integration with Home Assistant. I am using Mosquitto broker in HA. The ESP also serves a webpage with all the readings I have worked out. It appears to be working very reliably. Let me know if this works for you, if you have the same SmartView2 in home display.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h> //MQTT messaging
#include "Webpage.h"  //Wepage containing readings

const char* ssid = "Your SSID Here";
const char* password = "Your SSID Password Here";
const char* mqtt_server = "The IP of Your MQTT Broker";
const char* mqtt_user = "MQTT Username";
const char* mqtt_password = "MQTT Password";

char msg1[10];
char pkt[2];

bool bytSkp = false;

unsigned long startTime;
unsigned long endTime;
unsigned long elapsedTime;

ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);

String XMLData;
byte pktStart[1], pktEnd[1], packet[42];
long int meterRead1, meterRead2, meterRead3;
long int sMeterRead[18];
String sPacketx;
int header;
int i, j, bufLen;

void reconnect() {

  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("MQTT connecting...");

    // Create a client ID
    String clientId = "ESP8266-Client-";
    clientId += String(WiFi.macAddress());

    // Attempt to connect
    if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
      Serial.print("Connected.");
      Serial.println();

      // Once connected, publish an announcement...
      client.publish("energy/meterread", "Meter Readings.");
    } else {
      Serial.print("Failed. Retrying in 5 seconds...");

      // Wait 5 seconds before retrying
      delay(5000);
    }
  }

}

void setup() {

  // Configure serial ports
  Serial.begin(115200);
  Serial.setTimeout(4000);
  delay(10);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
   
  WiFi.begin(ssid, password);
   
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
   
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  server.on("/", sendWebsite);
  server.on("/emeter", sendXML);

  // Start the server
  server.begin();
  Serial.println("Server started");

  Serial.println("Connecting to MQTT server");
  client.setServer(mqtt_server, 1883);

}

void loop() {

  // Reconnect to MQTT if not connected
  if (!client.connected()){
    reconnect();
  }
  client.loop();

  // Wait for something in the serial buffer
  while(Serial.available() > 0) {
  
    // Clear the last packet read
    for(i = 0; i < sizeof(packet); i++) {
      packet[i] = 0;
    }  
    
    // Look for F1 start indicator
    Serial.readBytes(pktStart, 1);
    if(pktStart[0] == 0xF1) {
      // Read bytes until F2 is received
      Serial.readBytesUntil(0xF2, packet, 42);
    }  

    if(packet[0] == 0x04) {  
      sPacketx = "";
      j = 0;
      // Search for F3, to correct byte, and convert packet to a string
      for(i = 0; i < sizeof(packet); i++) {
        if(packet[i] == 0xF3) {
          bytSkp = true;
        }
        else {
          // Correct the F3 byte using the next byte
          if(bytSkp == true) {
            packet[j] = packet[i] + 0xF0;
            bytSkp = false;
          }
          else {
            packet[j] = packet[i];
          }
          sprintf(pkt, "%02s", (String(packet[j], HEX)));
          sPacketx = sPacketx + pkt + ",";
          j++;
        }
      }

      Serial.print(sPacketx + "\n");

      // Check which bytes to read
      header = (packet[4] * pow(16,2)) + packet[5];
      switch(header) {

        // Electricity current wattage (W)
        case 0x0702:
          meterRead1 = (packet[15] * pow(16, 4)) + (packet[14] * pow(16, 2)) + packet[13];
          sprintf(msg1, "%d", meterRead1);
          client.publish("electricity/current", msg1);
          sMeterRead[0] = meterRead1;
          break;

        // Gas current wattage not found        
        
        // Gas and electricity meter readings and use today (kWh)
        case 0x00:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          meterRead2 = (packet[20] * pow(16, 4)) + (packet[19] * pow(16,2)) + packet[18];
          if(packet[1] == 0x00) {
            sprintf(msg1, "%d", meterRead1);
            client.publish("gas/meter", msg1);
            sMeterRead[2] = meterRead1;
            sprintf(msg1, "%d", meterRead2);
            client.publish("gas/todayuse", msg1);
            sMeterRead[3] = meterRead2;
          }
          else {
            sprintf(msg1, "%d", meterRead1);
            client.publish("electricity/meter", msg1);
            sMeterRead[4] = meterRead1;
            sprintf(msg1, "%d", meterRead2);
            client.publish("electricity/todayuse", msg1);
            sMeterRead[5] = meterRead2;
            //sPacket4 = sPacketx;
            //sPacket5 = sPacketx;
          }
          break;

        // Gas and electricity costs today (£)
        case 0x1C05:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          if(packet[1] == 0x00) {
            sprintf(msg1, "%d", meterRead1);
            client.publish("gas/todaycost", msg1);
            sMeterRead[6] = meterRead1;
          }
          else {
            sprintf(msg1, "%d", meterRead1);
            client.publish("electricity/todaycost", msg1);
            sMeterRead[7] = meterRead1;
          }
          break;

        // Gas and Electricity meter balance (£)
        case 0x040A:
          meterRead1 = (packet[15] * pow(16, 4)) + (packet[14] * pow(16, 2)) + packet[13];
          if(packet[1] == 0x00) {
            sprintf(msg1, "%d", meterRead1);
            client.publish("gas/meterbalance", msg1);
            sMeterRead[8] = meterRead1;
          }
          else {
            sprintf(msg1, "%d", meterRead1);
            client.publish("electricity/meterbalance", msg1);
            sMeterRead[9] = meterRead1;
          }
          break;

        // Gas used yesterday (kWh)
        case 0x030C:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sprintf(msg1, "%d", meterRead1);
          client.publish("gas/yesterdayuse", msg1);
          sMeterRead[10] = meterRead1;
          break;

        // Electricity used yesterday (kWh)
        case 0x0304:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sprintf(msg1, "%d", meterRead1);
          client.publish("electricity/yesterdayuse", msg1);
          sMeterRead[11] = meterRead1;
          break;

        // Gas and electricity cost so far this week (£)
        case 0x3005:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          if(packet[1] == 0x00) {
            sprintf(msg1, "%d", meterRead1);
            client.publish("gas/weekcost", msg1);
            sMeterRead[12] = meterRead1;
          }
          else {
            sprintf(msg1, "%d", meterRead1);
            client.publish("electricity/weekcost", msg1);
            sMeterRead[13] = meterRead1;
          }
          break;

        // Gas used so far this week (kWh)
        case 0x300C:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sprintf(msg1, "%d", meterRead1);
          client.publish("gas/weekuse", msg1);
          sMeterRead[14] = meterRead1;
          break;

        // Electricity used so far this week (kWh)
        case 0x3004:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          sprintf(msg1, "%d", meterRead1);
          client.publish("electricity/weekuse", msg1);
          sMeterRead[15] = meterRead1;
          break;

        // Gas and electricity cost yesterday (£)
        case 0x1E05:
          meterRead1 = (packet[10] * pow(16, 4)) + (packet[9] * pow(16,2)) + packet[8];
          if(packet[1] == 0x00) {
            sprintf(msg1, "%d", meterRead1);
            client.publish("gas/yesterdaycost", msg1);
            sMeterRead[16] = meterRead1;
          }
          else {
            sprintf(msg1, "%d", meterRead1);
            client.publish("electricity/yesterdaycost", msg1);
            sMeterRead[17] = meterRead1;
          }
          break;

        default:
          break;

      }
    }
  }
  server.handleClient();
}

void sendWebsite() {

  server.send(200, "text/html", PAGE_MAIN);

}

void sendXML() {

  // XML data to send
  XMLData = "<?xml version=\'1.0\'?>";
  XMLData += "<readings>";
  XMLData += "<result><value>" + String(sMeterRead[0]) + "</value><reading>Electricity Current Wattage (W)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[2]) + "</value><reading>Gas Meter Reading (m3)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[8]) + "</value><reading>Gas Meter Balance (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[4]) + "</value><reading>Electricity Meter Reading (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[9]) + "</value><reading>Electricity Meter Balance (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[3]) + "</value><reading>Gas Use Today (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[6]) + "</value><reading>Gas Cost Today (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[5]) + "</value><reading>Electricity Use Today (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[7]) + "</value><reading>Electricity Cost Today (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[10]) + "</value><reading>Gas Used Yesterday (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[16]) + "</value><reading>Gas Cost Yesterday (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[11]) + "</value><reading>Electricity Used Yesterday (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[17]) + "</value><reading>Electricity Cost Yesterday (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[14]) + "</value><reading>Gas Used This Week (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[12]) + "</value><reading>Gas Cost This Week (£)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[15]) + "</value><reading>Electricity Used This Week (kWh)</reading></result>";
  XMLData += "<result><value>" + String(sMeterRead[13]) + "</value><reading>Electricity Cost This Week (£)</reading></result>";
  XMLData += "</readings>";

  server.send(200, "text/xml", XMLData);

}

Webpage.h

const char PAGE_MAIN[] PROGMEM = R"=====(

<!DOCTYPE HTML>
<html lang="en" class="js-focus-visible">

<title>SmartView2 Readings</title>

<head>
<style>
  table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
    font-family: "Courier New";
  }
</style>
</head>

<body onload="loadDoc()">

<script type = "text/javascript">
  function loadDoc() {
    const xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        updateReadings(this);
      }
    }
    xhttp.open("GET", "/emeter");
    xhttp.send();
    setTimeout(loadDoc, 200);
  }

  function updateReadings(xml) {
    var xmlDoc, x, i, results;
    
    xmlDoc = xml.responseXML;
    x = xmlDoc.getElementsByTagName("result");
    results = "<tr><th>Value</th><th>Reading</th></tr>";
    for (i = 0; i< x.length; i++) {
      results += "<tr><td>" + x[i].childNodes[0].childNodes[0].nodeValue + "</td><td>" + x[i].childNodes[1].childNodes[0].nodeValue + "</td></tr>";
    }
    document.getElementById("results").innerHTML = results;
  }
</script>

<table style="width:100%" id="results"></table>

</body>
</html>

)=====";

configuration.yaml

mqtt:
  sensor:
    - name: "Electricity Current Wattage"
      state_topic: "electricity/current"
      unit_of_measurement: "W"
    - name: "Electricity Meter Reading"
      state_topic: "electricity/meter"
      unit_of_measurement: "kWh"
      value_template: >- 
        {%- set reading = value | int -%}
        {{ '{:09}'.format(reading/1000) }}
      device_class: energy
      state_class: total
    - name: "Electricity Use Today"
      state_topic: "electricity/todayuse"
      unit_of_measurement: "kWh"
      value_template: >-
        {%- set reading = value | int -%}
        {{ reading/1000 }}
    - name: "Electricity Cost Today"
      state_topic: "electricity/todaycost"
      unit_of_measurement: "£"
      icon: "mdi:currency-gbp"
      value_template: >-
        {%- set reading = value | int -%}
        {{ (reading/100000) | round(2) }}
    - name: "Gas Meter Reading"
      state_topic: "gas/meter"
      unit_of_measurement: "m³"
      value_template: >-
        {%- set reading = value | int -%}
        {{ '{:09}'.format(reading/1000) }}
      device_class: gas
      state_class: total
    - name: "Gas Use Today"
      state_topic: "gas/todayuse"
      unit_of_measurement: "kWh"
      value_template: >-
        {%- set reading = value | int -%}
        {{ reading/1000 }}
    - name: "Gas Cost Today"
      state_topic: "gas/todaycost"
      unit_of_measurement: "£"
      icon: "mdi:currency-gbp"
      value_template: >-
        {%- set reading = value | int -%}
        {{ (reading/100000) | round(2) }}

Home Assistant Dashboard
image