Connecting to my analog espresso machine

Hello!
I would like to show you my current project. Last year I bought this great espresso machine. It takes some time to heat up. And once it is heated up it delivers excellent espresso.

After some time I thought it would be a good idea to use a z wave wall plug connected
to my openhab to turn it on. Now I can sleep 15 min longer and the espresso machine is already heated up when I go in the morning to the kitchen to get some espresso and go back to bed. This set up worked great.

But after some time I once in a while forget to fill up the water so I get to the kitchen and notice that the espresso machine has not heated up because of no water. This was really annoying because I had to refill the water and wait again 15 min. I came to the idea to look into the analysis within openhab of the energy meter which the wall plug provides and found some correlations between Standby, no water, ready, pulling coffee and heating up so began with the code below.

It works fine now for me and notifies me about the different status of the machine via telegram binding. It is really nice and I do not have to go back and forth between my working place or bedroom and the kitchen to check if the machine is ready. I know this is kind of nerdy. But I do like it.

Please check it out and let me know what you think. If you see areas of improvement please let me know. I am not a very experienced programmer so the code might look arkward but I am open to learn. I have not cleaned it up completely and the comments are a little bit messy and incomplete but I guess you will get the idea. I will also add a screenshot of the energy curve later on so you can compare.


//espresso machine state
//tailored to work with a 
//Lelit Mara X 2021
//connected to a Fibaro Wallplug
//script is executed via a rule 
//triggered when wallbug switches from off
//to on
//retrieves espresso machine state
//based on energy consumption levels in kwh
//returns state in human readable
//form and sends out 
//notification via telegram
//since this is a water boiler 
//situation does not change very quickly
//sampling intervall is set to
//one minute
//pulling coffee is experimental
//could be used to count espressos but depending on double or single setup
//once ready is reached it cannot go to heatup again 
//for the customer this is not relevant
//number if samplikg intervals is defined
//by the sampling interval and the maximum lebgth during
//heatup phase 
// than one can make sure that ready state has reaaly been resched or
// the machine is still in heatup phase

var interest = items.getItem('ZWaveNode008FGWP102MeteredWallPlugSwitch_Sensorpower');
var parsed = parseFloat(interest.state);
var telegramAction = actions.get("telegram","telegram:telegramBot:1774a671e0");
var ret_str = "hello";
var status_old = 0;
var parsed_old_old = 0;
var schritt;
var status = 1;
var parsed_old = 1;
var sampling_interval = 15000;
//var arrStatus = [];
//arrStatus.length = 10;
//var arrParsed = [];
//arrParsed.length = 10;
//arrParsed.length = //round(sampling_intervall/10);

function doNotify(parsed, parsed_old, parsed_old_old, status){
  //makes the numbers to match
  //human readable notification
  //can be translated into
  //whatever
  //sends out notification
  //via telegram binding
  switch (status){
  case 0:
    ret_str = "off";
    break;
  case 1:
    ret_str="standby";
    break;
  case 2:
    ret_str="nowater";
    break;
  case 3:
    ret_str="ready";
    break;
  case 4:
    ret_str="heatingup";
    break;
  case 5:
    ret_str="pullingcoffee";
    break;
  }
  //telegramAction.sendTelegram("Status: " + ret_str + " " + parsed + " " + parsed_old + " " + parsed_old_old);
  telegramAction.sendTelegram("Status: " + ret_str);
}

function doStateChange(parsed, parsed_old, parsed_old_old, status){
  //core ip of this program
  //probably needs to be adjusted
  //depending on coffee machine
  //i checked the values and matched
  //them to the status of the machine
  if (parsed == 0){
      status = 0;
    }
  else if (parsed < 1.1 && parsed_old < 1.1 && parsed_old_old < 1.1 && status != 5){
      status = 1;
    }
  else if (parsed < 1.3 && parsed_old < 1.3 && parsed_old_old < 1.3){
      status = 2;
    }
  else if ((parsed < 2  && parsed_old < 2 && parsed_old_old < 2) || (parsed < 2 && status == 5)){
      status = 3;
    }
  else if (parsed < 1307 && status != 3){
       status = 4;
    }
  else if (parsed > 1307){
      status = 5;
    }
  return status;
}

function getValue(interest, parsed){
  //gets the current value
  //from the item
  //parses to be float
  parsed = parseFloat(interest.state);
  return parsed;
}

function doStateCheck(status, status_old){
  //checks if status has changed
  //returns true when it has chsnged
  //false if it has not changed
  if (status != status_old){
    return true;
  }else {
    return false;
  }
}

function sleep(ms) {
  //only sample every x ms
  //timeout needed
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function main() {
  // Pause execution of this async function for 2 seconds
  // telegramAction.sendTelegram("Main Started");
  while(status>0){
  //for  (schritt = 0; schritt < 5; schritt++) {
    await sleep(sampling_interval);
    parsed_old_old = parsed_old;
    parsed_old = parsed;
    status_old = status;
    parsed = getValue(interest, parsed);
    status = doStateChange(parsed, parsed_old, parsed_old_old, status);
    if (doStateCheck(status, status_old)){
      doNotify(parsed, parsed_old, parsed_old_old, status);
    }
  }
  //telegramAction.sendTelegram("While ended");
}

main();


4 Likes