SenseLink and Shelly EM Gen3 with CT Clamps: One unit monitoring TWO circuits

Using Shelly EM Gen3 CT Clamps with SenseLink to monitor circuits that Sense has a hard time discovering.

Each Shelly EM Gen3 can monitor TWO circuits with two separate CT clamps.

Let me start of my stating that I am not an expert but was just tinkering around to be able to monitor more circuits in my all electric house–in particular oven, cooktop, dryer and mini split inverter.

I used a Raspberry Pi 3B and installed SenseLink via Docker and MQTT broker. Before installing the Shelly EM Gen3 into my circuit breaker box, I set it up outside and labeled the units. I read many topics to try to figure out which parameters to use but, in the end it was trial and error. I hope this helps anyone who is clueless like me be able to tackle this project.

Key steps:

Shelly EM Gen3: Installed in breaker box with a separate 15A double pole breaker (to monitor 240V). Each CT clamps to each circuit you want to monitor. Labeling them will help identify correct circuits.

Enable MQTT on Shelly device (via app), Server use your Pi IP, MQTT Prefix: unique name like “shelly-unit1” “shelly-unit2” (remember each unit can monitor 2 circuits)

When installing onto the circuit you want to monitor, it does not matter which directions. If it is negative, you can always use the Shelly app to change.

Senselink yaml was a challenge for me…this is what I did for it to work

Sorry the spacing is not correct for copy and paste into your own senselink.yaml

sources:


- mqtt:

host:                        #use your Pi static IP

port: 1883               #must us this port number

username: " "         #empty if no auth

password: “ “         #empty if no auth

plugs:

*   Oven:
  alias: "Oven"                                                 #name that shows up in Sense
  mac: "e4:b0:63:d4:a4:01"                             #make up any mac but different for each
  power_topic: "shelly-unit1/status/em1:0"     #0 or 1 at the end specify which clamp
  power_topic_keypath: act_power                #act_power reports the watts
  apower multiplier: 1                                     #not sure if this is needed

*   Cooktop:
  alias: "Cooktop"
  mac: "e4:b0:63:d4:a4:02"
  power_topic: "shelly-unit1/status/em1:1"
  power_topic_keypath: act_power
  apower multiplier: 1

*   Dryer:
  alias: "Dryer"
  mac: "e4:b0:63:d4:4c:03"
  power_topic: "shelly-unit2/status/em1:0"
  power_topic_keypath: act_power
  apower multiplier: 1

*   MiniSpit:
  alias: "MiniSplit"
  mac: "e4:b0:63:d4:4c:04"
  power_topic: "shelly-unit2/status/em1:1"
  power_topic_keypath: act_power
  apower multiplier: 1

destinations:

sense:

username:             #your sense account

password:             #your sense password
3 Likes

Nice job @thomastran.rx1 ! Great to see how you integrated the Shelly’s using Home Assistant and Senselink. I did a minor edit to your posting - I selected your source code and applied the preformatted text formatting (</>) to it. Hope you don’t mind.

The spacing in the yaml does make a difference so here’s what it looks like.

To my understanding Shelly EM Gen3 uses “act_power” to report watts while older Gen1 and Shelly PM uses “apower”. I tried apower with Shelly EM Gen3 and it was a no go.

1 Like

To correct for negative watts when idle run this script in Shelly app:

// Configuration: Set your noise threshold (e.g., -10W to 0W)
let CONFIG = {
  threshold: -10, // Values between -10 and 0 will be treated as 0
  phase: 0        // 0 for Phase A, 1 for Phase B
};

function checkPower() {
  Shelly.call("EM.GetStatus", { id: 0 }, function (result) {
    let power = result.act_power;
    
    // Logic: If power is slightly negative, treat it as zero
    let filteredPower = (power < 0 && power >= CONFIG.threshold) ? 0 : power;
    
    // Log the result to the console for verification
    print("Raw Power:", power, "W | Filtered Power:", filteredPower, "W");
    
    // You can add logic here to trigger other devices or send data to a server
  });
}

// Run the check every 1 second
Timer.set(500, true, checkPower);