Smappee

Pierre Kil edited this page Jan 14, 2017 · 6 revisions

Smappee is a device that measures the energy consumption of your electrical appliances with one sensor. If you have solar panels, you can also use Smappee to measure the energy generated. The Smappee app gives you direct insight into your energy consumption, energy costs and the yield of your solar panels. It has IFTTT channel (this is how I discovered it BTW), however integrating it with Openremote increases its possibilities and responsiveness. Events are updated with maximum delay of 60s, while IFTTT typical response times are 5 to 15 minutes -- quite long time if you wish to turn on your radio/TV when the morning coffee is ready :-)

Smappee support is still in development phase and not released as part of downloadable OpenRemote binaries. Therefore you will need to manually include the required files into your OpenRemote Controller install as described below.

This document is still in progress and will be updated before the final version will be available.

##Introduction

The Smappee integration is performed employing already integrated protocols (HTTP + Shell execution protocol) and Drools rule engine. It presents an example how new protocols can be easily added to Openremote without the need of building a new binary. The main reason for me doing it this way is the fact that Smappee uses oauth2 authentication, which is unavailable in Openremote at the moment of this writing.

##Hardware

For a complete setup, you will need:

  1. Smappee
  2. OpenRemote Controller installed on your eBox, PC, RPi, NAS, etc.. This how-to is based on eBox with designer pro.
  3. OpenRemote Designer Account
  4. A web browser, Android or iOS device for control
  5. Additional automation controls for lighting, curtains, switches, etc.

##Configuration of System

Pre-requisites:

apt-get install curl

###Shell scripts installation

Login int ebox with ssh:

ssh root@orb

Create shell scripts which will be used to communicate with the Smappee cloud. Check if the curl is installed. In case of absence do:

apt-get install curl

Then install scripts:

mkdir /root/smappee
cd smappee
root@orb ~/smappee> cat ClientCredentials.sh 
curl -X POST https://app1pub.smappee.net/dev/v1/oauth2/token -d "grant_type=password&client_id=[CLIENT_ID]&client_secret=[CLIENT_SECRET]&username=[USERNAME]&password=[PASSWORD]"
root@orb ~/smappee> cat Consumption1.sh 
curl -X GET -H "Authorization: Bearer $1"  "https://app1pub.smappee.net/dev/v1/servicelocation/$2/consumption?aggregation=1&from=$3&to=$4" > /opt/OpenRemote-Controller/webapps/controller/Consumption1.json
root@orb ~/smappee> cat Events.sh
curl -X GET -H "Authorization: Bearer $1"  "https://app1pub.smappee.net/dev/v1/servicelocation/$2/events?$5maxNumber=$6&from=$3&to=$4"  > /opt/OpenRemote-Controller/webapps/controller/Events.json
root@orb ~/smappee> cat ServicelocationInfo.sh
curl -X GET -H "Authorization: Bearer $1"  https://app1pub.smappee.net/dev/v1/servicelocation/$2/info > /opt/OpenRemote-Controller/webapps/controller/ServicelocationInfo.json
root@orb ~/smappee> cat Servicelocations.sh
curl -X GET -H "Authorization: Bearer $1"  https://app1pub.smappee.net/dev/v1/servicelocation > /opt/OpenRemote-Controller/webapps/controller/Servicelocations.json
root@orb:~/smappee# ll
total 20
-rw-r--r-- 1 root root 178 Dec  4 12:20 ClientCredentials.sh
-rw-r--r-- 1 root root 205 Dec  4 12:20 Consumption1.sh
-rw-r--r-- 1 root root 196 Dec  4 12:20 Events.sh
-rw-r--r-- 1 root root 175 Dec  4 12:20 ServicelocationInfo.sh
-rw-r--r-- 1 root root 164 Dec  4 12:20 Servicelocations.sh

For credentials request a client_id & client_secret by sending an email to support(AT)smappee.com. Username and password should be the same which you use to login at https://my.smappee.com/ For easier install I've created smappee.zip, which you can use after amending ClientCredentials.sh with the actual data.

###Create Smappee commands

####Shell-execution protocol

6 commands:

-rw-rw-rw- 1 root root   137 Dec  4 14:13 /opt/OpenRemote-Controller/bin/SmappeeActuator.sh
-rw-rw-rw- 1 root root   167 Dec  4 14:13 /opt/OpenRemote-Controller/bin/SmappeeClientCredentials.sh
-rw-rw-rw- 1 root root   181 Dec  4 14:13 /opt/OpenRemote-Controller/bin/SmappeeConsumption1.sh
-rw-rw-rw- 1 root root   172 Dec  4 14:13 /opt/OpenRemote-Controller/bin/SmappeeEvents.sh
-rw-rw-rw- 1 root root   151 Dec  4 14:13 /opt/OpenRemote-Controller/bin/SmappeeServicelocationInfo.sh
-rw-rw-rw- 1 root root   140 Dec  4 14:13 /opt/OpenRemote-Controller/bin/SmappeeServicelocations.sh

####HTTP protocol

All GET with 15s pooling interval. Events.json can have faster pooling for better responsiveness.

Urls:

These commands simply read output of the shell commands which employ curl calls.

####Sensors

All these sensors are custom type sensors and their commands are the same as the corresponding sensor names.

  • ClientCredentials.sh
  • Servicelocations.json
  • Consumption1.json
  • ServicelocationInfo.json
  • Events.json

####Rules

package org.openremote.controller.protocol;

import java.util.*;
import java.io.*;
// For email
import javax.mail.*;
import javax.mail.internet.*;
// For email
// For logger
import org.openremote.controller.utils.Logger;
import org.openremote.controller.Constants;

function void log(String msg)
{
  Logger.getLogger(Constants.RUNTIME_EVENTPROCESSOR_LOG_CATEGORY + ".drools").debug(msg);
}

// Smappee

declare SmappeeInit
  @role(event)
  id: int
end

rule "-Smappee: Init"
salience 10
when
then
  insert(new SmappeeInit());
  // Create scripts for shell commands:
  PrintWriter writer;
  // writer = new PrintWriter("SmappeeClientCredentials.sh", "UTF-8");
  //try{writer.println("curl -X POST https://app1pub.smappee.net/dev/v1/oauth2/token -d \"grant_type=password&client_id=&client_secret=&username=&password=\"");}finally{writer.close();}
  writer = new PrintWriter("SmappeeServicelocations.sh", "UTF-8");
  try{writer.println("curl -X GET -H \"Authorization: Bearer $1\"  https://app1pub.smappee.net/dev/v1/servicelocation > ../webapps/controller/Servicelocations.json");}finally{writer.close();}
  writer = new PrintWriter("SmappeeServicelocationInfo.sh", "UTF-8");
  try{writer.println("curl -X GET -H \"Authorization: Bearer $1\"  https://app1pub.smappee.net/dev/v1/servicelocation/$2/info > ../webapps/controller/ServicelocationInfo.json");}finally{writer.close();}
  writer = new PrintWriter("SmappeeConsumption1.sh", "UTF-8");
  try{writer.println("curl -X GET -H \"Authorization: Bearer $1\"  \"https://app1pub.smappee.net/dev/v1/servicelocation/$2/consumption?aggregation=1&from=$3&to=$4\" > ../webapps/controller/Consumption1.json");}finally{writer.close();}
  writer = new PrintWriter("SmappeeEvents.sh", "UTF-8");
  try{writer.println("curl -X GET -H \"Authorization: Bearer $1\"  \"https://app1pub.smappee.net/dev/v1/servicelocation/$2/events?$5maxNumber=$6&from=$3&to=$4\"  > ../webapps/controller/Events.json");}finally{writer.close();}
  writer = new PrintWriter("SmappeeActuator.sh", "UTF-8");
  try{writer.println("curl -X POST -H \"Authorization: Bearer $1\" -d \"{\\\"duration\\\"=$5}\" \"https://app1pub.smappee.net/dev/v1/servicelocation/$2/actuator/$3/$4\"");}finally{writer.close();}
end

declare SmappeeClientCredentials
  @role(event)
  @expires(12h)
  access_token  : String
  refresh_token : String
  expires_in      : int
end

rule "Smappee: Parse Client Credentials"
when
  $e: Event(source=="ClientCredentials.sh", $v: value!="")
then
  SmappeeClientCredentials cred = new flexjson.JSONDeserializer<SmappeeClientCredentials>().deserialize($v.toString(), SmappeeClientCredentials.class );
  insert(cred);
  retract($e);
end

rule "Smappee: delete old cred"
salience 10
when
  $c: SmappeeClientCredentials()
  SmappeeClientCredentials(this after $c)
then
  retract($c);
end

declare SmappeeServicelocations
  @role(event)
  @expires(7m)
  appName : String
  serviceLocations : List
end

declare SmappeeServiceLocation
  @role(event)
  @expires(7m)
  serviceLocationId : int
  name : String
end

declare ExecDelay
  @role(event)
  @expires(10s) // Give time for shell script execution
  source: String
end

rule "--Smappee: Parse Servicelocations.json"
when
  $e: Event(source=="Servicelocations.json", $v: value!="")
  exists SmappeeClientCredentials()
  not SmappeeServicelocations()
  not ExecDelay(source=="Servicelocations")
then
  List<SmappeeServiceLocation> items = new flexjson.JSONDeserializer<Map<String,List<SmappeeServiceLocation>>>().use("values.values", SmappeeServiceLocation.class).deserialize($v.toString(), Map.class).get("serviceLocations");
  SmappeeServicelocations servicelocation = new flexjson.JSONDeserializer<SmappeeServicelocations>().deserialize( $v.toString(), SmappeeServicelocations.class );
  for(SmappeeServiceLocation r: items){
    insert(r);
  }
  servicelocation.setServiceLocations(items);
  insert(servicelocation);
  retract($e);
end

declare  SmappeeAppliance
  @role(event)
  @expires(7m)
  id: int
  name: String
  type: String
  power: double
end

declare  SmappeeActuator
  @role(event)
  @expires(7m)
  id: int
  name: String
end

declare  SmappeeActuatorCopy
  @role(event)
  @expires(7m)
  id: int
  name: String
end

declare  SmappeeApplianceCopy
  @role(event)
  id: int
  name: String
  type: String
  power: double
  timestamp: long
end

rule "Smappee: appliance insert"
timer(int: 30s)
when
  SmappeeAppliance($id: id, $name: name, $type: type, $power: power)
  not SmappeeApplianceCopy(id==$id, name==$name, type==$type)
  not SmappeeInit()
then
  SmappeeApplianceCopy apc = new SmappeeApplianceCopy();
  apc.setId($id);
  apc.setName($name);
  apc.setType($type);
  apc.setPower($power);
  insert(apc);

  insert(new Email_Text_Message("New Smappee appliance \""+$id+":"+$name+"\" inserted @"+_TimeStamp1((new Date()).getTime()),""));
end

rule "--Smappee: appliance delete"
timer(int: 1m) // Give 2m to parse json data after expiration of SmappeeAppliance
when
  $r: SmappeeApplianceCopy($id: id, $name: name, $type: type)
  not SmappeeAppliance(id==$id, name==$name, type==$type)
  not SmappeeInit()
then
  insert(new Email_Text_Message("Obsolete Smappee appliance \""+$id+":"+$name+"\" deleted @"+_TimeStamp1((new Date()).getTime()-120000),""));
  retract($r);
end

rule "Smappee: appliance rename"
when
  SmappeeAppliance($id: id, $name: name, $type: type)
  $sc: SmappeeApplianceCopy(id==$id, name!=$name || type!=$type)
then
  $sc.setName($name);
  $sc.setType($type);
  update($sc);
  insert(new Email_Text_Message("Smappee appliance \""+$id+":"+$name+"\" renamed @"+_TimeStamp1((new Date()).getTime()-120000),""));
end

declare SmappeeAppliances
  @role(event)
  @expires(7m)
  lon: double
  lat: double
  electricityCost: double
  electricityCurrency: String
  appliances: List
  actuators: List
  serviceLocationId: int
  name: String
end

rule "--Smappee: Parse ServicelocationInfo.json"
when
  $e: Event(source=="ServicelocationInfo.json", $v: value!="")
  exists SmappeeClientCredentials()
  exists SmappeeServiceLocation()
  not SmappeeAppliances()
  not ExecDelay(source=="ServicelocationInfo")
  not SmappeeInit()
then
  List<SmappeeAppliance> appliance = new flexjson.JSONDeserializer<Map<String,List<SmappeeAppliance>>>().use("values.values", SmappeeAppliance.class).deserialize($v.toString(), Map.class).get("appliances");
  List<SmappeeActuator> actuators = new flexjson.JSONDeserializer<Map<String,List<SmappeeActuator>>>().use("values.values", SmappeeActuator.class).deserialize($v.toString(), Map.class).get("actuators");
  SmappeeAppliances appliances = new flexjson.JSONDeserializer<SmappeeAppliances>().deserialize( $v.toString(), SmappeeAppliances.class );
  for(SmappeeActuator r: actuators){
    insert(r);
  }
  for(SmappeeAppliance r: appliance){
    insert(r);
  }
  appliances.setAppliances(appliance);
  appliances.setActuators(actuators);
  insert(appliances);
  retract($e);
end

rule "Smappee: Parse ServicelocationInfo.json init"
when
  $e: Event(source=="ServicelocationInfo.json", $v: value!="")
  not SmappeeAppliances()
  not ExecDelay(source=="ServicelocationInfo")
  $i: SmappeeInit()
then
  List<SmappeeAppliance> appliance = new flexjson.JSONDeserializer<Map<String,List<SmappeeAppliance>>>().use("values.values", SmappeeAppliance.class).deserialize($v.toString(), Map.class).get("appliances");
  List<SmappeeActuator> actuators = new flexjson.JSONDeserializer<Map<String,List<SmappeeActuator>>>().use("values.values", SmappeeActuator.class).deserialize($v.toString(), Map.class).get("actuators");
  SmappeeAppliances appliances = new flexjson.JSONDeserializer<SmappeeAppliances>().deserialize( $v.toString(), SmappeeAppliances.class );
  for(SmappeeActuator r: actuators){
    insert(new SmappeeActuatorCopy(r.getId(), r.getName()));
    insert(r);
  }
  for(SmappeeAppliance r: appliance){
    SmappeeApplianceCopy apc = new SmappeeApplianceCopy();
    apc.setId(r.getId());
    apc.setName(r.getName());
    apc.setType(r.getType());
    insert(apc);
    insert(r);
  }
  appliances.setAppliances(appliance);
  appliances.setActuators(actuators);
  insert(appliances);
  retract($e);
  retract($i);
end

declare SmappeeConsumptions
  @role(event)
  @expires(1m)
  serviceLocationId: int
  consumptions: List
end

declare SmappeeConsumption
  @role(event)
  @expires(1m)
  timestamp: long
  consumption: double
  solar: double
  alwaysOn: double
end

rule "--Smappee: Parse Consumption1.json"
when
  Event(source=="Consumption1.json", $v: value!="")
  not SmappeeConsumptions()
  not SmappeeConsumption()
  not ExecDelay(source=="Consumption1")
then
  List<SmappeeConsumption> consumption = new flexjson.JSONDeserializer<Map<String,List<SmappeeConsumption>>>().use("values.values", SmappeeConsumption.class).deserialize($v.toString(), Map.class).get("consumptions");
  SmappeeConsumptions consumptions = new flexjson.JSONDeserializer<SmappeeConsumptions>().deserialize( $v.toString(), SmappeeConsumptions.class );
  for(SmappeeConsumption r: consumption){
    insert(r);
    execute.command("VSMAPCONS5m", String.format("%.1f", r.getConsumption()*12.0));
    execute.command("VSMAPCONS5mAO", String.format("%.1f W", r.getAlwaysOn()));
    execute.command("VSMAPCONS5mTS", "@ "+_TimeStamp1(r.getTimestamp()));
  }
  insert(consumptions);
end

declare SmappeeEvent
  @role(event)
  activePower: Double
  applianceId: int
  timestamp: long
end

rule "--Smappee: Parse Events.json"
when
  Event(source=="Events.json", $v: value!="")
  exists SmappeeClientCredentials()
  exists SmappeeServicelocations()
  not ExecDelay(source=="Events")
then
  List<SmappeeEvent> event = new flexjson.JSONDeserializer<List<SmappeeEvent>>().use("values", SmappeeEvent.class).deserialize($v.toString(), List.class);
  for(SmappeeEvent e:event){
    insert(e);
  }
end

rule "--Smappee: retract double events"
salience 10
when
  $e: SmappeeEvent($a:activePower, $i: applianceId, $t: timestamp)
  SmappeeEvent(activePower==$a, applianceId==$i, timestamp==$t, this before $e)
then
  retract($e);
end

rule "--Smappee: retract old events"
salience 5
when
  SmappeeEvent($i: applianceId, $t: timestamp)
  not SmappeeEvent(applianceId==$i, timestamp > $t)
  $e: ArrayList(size>0) from collect(SmappeeEvent(applianceId==$i, timestamp < $t))
then
  for(Object e: $e){
    retract(e);
  }
end

rule "--Smappee: show event"
salience (-$ts)
no-loop true
when
  $sev: SmappeeEvent($id: applianceId, $ts: timestamp, $ap: activePower)
  $apc: SmappeeApplianceCopy(id==$id, $name:name, timestamp<$ts)
  $apl: SmappeeAppliance(id==$id)
then
  $apc.setPower($ap);
  $apl.setPower($ap);
  $apc.setTimestamp($ts);
  update($apc);
  update($apl);
  
  log("Smappee: show event for "+$name+" - "+$sev);

//  execute.command("VLASTEVENTAppliance", $name);
//  execute.command("VLASTEVENTApplianceTS", _TimeStamp2($ts));
//  execute.command("VLASTEVENTAppliancePower", String.format("%.1f W", $ap));
end

rule "Smappee: no max power"
timer(int: 2s) // give time to propagate to UI and back
when
  SmappeeAppliance($id:id, power<=0)
  Event($s:source matches "VLASTEVENTApplianceTS(P*)", eval(String.format("%d",$id).equals(value.toString())))
then
  String ps=$s.substring(21);
  execute.command("VLASTEVENTAppliance"+ps, "-");
  execute.command("VLASTEVENTAppliancePower"+ps, "-");
  execute.command($s, "-");
end

rule "--Smappee: copy power"
when
  SmappeeApplianceCopy($p: power, $i: id)
  $a: SmappeeAppliance(power!=$p, id==$i)
then
  $a.setPower($p);
  update($a);
  if($p>0){
    log("Smappee: copy power - "+$a);
  }
end

rule "Smappee: max power appliance-0"
timer(int:100ms) // Need to wait for all appliances update therefore better delay than salience
when
  $a: SmappeeAppliance($p: power>0, $n: name, $i: id)
  not SmappeeAppliance(power > $p)
then
  if($n.equals("")){
    execute.command("VLASTEVENTApplianceP",  "#"+$i);
  }else{
    execute.command("VLASTEVENTApplianceP", $n);
  }
  execute.command("VLASTEVENTAppliancePowerP", String.format("%.1f W", $p));
  execute.command("VLASTEVENTApplianceTSP", ""+$i);
  // insert(new Email_Text_Message($n+" "+String.format("%.1f W", $p),"" ));
end

rule "Smappee: max power appliance-1"
timer(int:110ms)
when
  $a: SmappeeAppliance($p: power>0, $n: name, $i: id)
  Number(intValue==1) from accumulate($x: SmappeeAppliance(power>$p), count($x))
then
  if($n.equals("")){
    execute.command("VLASTEVENTAppliancePP", "#"+$i);
  }else{
    execute.command("VLASTEVENTAppliancePP", $n);
  }
  execute.command("VLASTEVENTAppliancePowerPP", String.format("%.1f W", $p));
  execute.command("VLASTEVENTApplianceTSPP", String.format("%d", $i));
end

rule "Smappee: max power appliance-2"
timer(int:120ms)
when
  $a: SmappeeAppliance($p: power>0, $n: name, $i: id)
  Number(intValue==2) from accumulate($x: SmappeeAppliance(power>$p), count($x))
then
  if($n.equals("")){
    execute.command("VLASTEVENTAppliancePPP", "#"+$i);
  }else{
    execute.command("VLASTEVENTAppliancePPP", $n);
  }
  execute.command("VLASTEVENTAppliancePowerPPP", String.format("%.1f W", $p));
  execute.command("VLASTEVENTApplianceTSPPP", String.format("%d", $i));
end

rule "Smappee: max power appliance-3"
timer(int:130ms)
when
  $a: SmappeeAppliance($p: power>0, $n: name, $i: id)
  Number(intValue==3) from accumulate($x: SmappeeAppliance(power>$p), count($x))
then
  if($n.equals("")){
    execute.command("VLASTEVENTAppliancePPPP", "#"+$i);
  }else{
    execute.command("VLASTEVENTAppliancePPPP", $n);
  }
  execute.command("VLASTEVENTAppliancePowerPPPP", String.format("%.1f W", $p));
  execute.command("VLASTEVENTApplianceTSPPPP", String.format("%d", $i));
end

rule "Smappee: max power appliance-4"
timer(int:130ms)
when
  $a: SmappeeAppliance($p: power>0, $n: name, $i: id)
  Number(intValue==4) from accumulate($x: SmappeeAppliance(power>$p), count($x))
then
  if($n.equals("")){
    execute.command("VLASTEVENTAppliancePPPPP", "#"+$i);
  }else{
    execute.command("VLASTEVENTAppliancePPPPP", $n);
  }
  execute.command("VLASTEVENTAppliancePowerPPPPP", String.format("%.1f W", $p));
  execute.command("VLASTEVENTApplianceTSPPPPP", String.format("%d", $i));
end

rule "Smappee: clear empty rows-0"
when
  not SmappeeApplianceCopy(power>0)
then
  execute.command("VLASTEVENTApplianceP", "-");
  execute.command("VLASTEVENTAppliancePowerP", "-");
  execute.command("VLASTEVENTApplianceTSP", "-");
end

rule "Smappee: clear empty rows-1"
when
  exists SmappeeApplianceCopy(power>0)
  Number(intValue<=1) from accumulate($i:SmappeeApplianceCopy(power>0), count($i))
then
  execute.command("VLASTEVENTAppliancePP", "-");
  execute.command("VLASTEVENTAppliancePowerPP", "-");
  execute.command("VLASTEVENTApplianceTSPP", "-");
end

rule "Smappee: clear empty rows-2"
when
  exists SmappeeApplianceCopy(power>0)
  Number(intValue<=2) from accumulate($i:SmappeeApplianceCopy(power>0), count($i))
then
  execute.command("VLASTEVENTAppliancePPP", "-");
  execute.command("VLASTEVENTAppliancePowerPPP", "-");
  execute.command("VLASTEVENTApplianceTSPPP", "-");
end

rule "Smappee: clear empty rows-3"
when
  exists SmappeeApplianceCopy(power>0)
  Number(intValue<=3) from accumulate($i:SmappeeApplianceCopy(power>0), count($i))
then
  execute.command("VLASTEVENTAppliancePPPP", "-");
  execute.command("VLASTEVENTAppliancePowerPPPP", "-");
  execute.command("VLASTEVENTApplianceTSPPPP", "-");
end

rule "Smappee: clear empty rows-4"
when
  exists SmappeeApplianceCopy(power>0)
  Number(intValue<=4) from accumulate($i:SmappeeApplianceCopy(power>0), count($i))
then
  execute.command("VLASTEVENTAppliancePPPPP", "-");
  execute.command("VLASTEVENTAppliancePowerPPPPP", "-");
  execute.command("VLASTEVENTApplianceTSPPPPP", "-");
end

rule "--Smappee: delete row"
timer(int:300ms)
no-loop true
when
  $e: Event($s:source matches "VLASTEVENTAppliancePowerP+", value=="OFF")
  Event(source matches ("VLASTEVENTApplianceTS"+$s.substring(24)), $v:value!="-")
  $ev: SmappeeEvent(eval(applianceId==Integer.parseInt($v.toString())))
then
  execute.command($s,"-");
  $ev.setActivePower(-$ev.getActivePower());
  $ev.setTimestamp((new Date()).getTime());
  update($ev);
end

rule "Smappee: delete row clear"
salience -10
timer(int:350ms)
when
  Event($s:source matches "VLASTEVENTAppliancePowerP+", value=="OFF")
then
  execute.command($s,"-");
end

rule "--Smappee: active power"
when
  exists SmappeeApplianceCopy()
  Number($power: doubleValue) from accumulate(SmappeeApplianceCopy($p: power>0), sum($p))
  Number($count: intValue) from accumulate($i:SmappeeApplianceCopy(power>0), count($i))
then
  execute.command("VACTIVEPOWER", $power+" W ("+$count+")");
end

rule "--Smappee: events sanity check"
when
  SmappeeConsumption($cons: consumption, $ao: alwaysOn, $cts: timestamp)
  $ev: SmappeeEvent($ap:activePower > ($cons*12.0-$ao), $ets: timestamp < $cts)
then
  $ev.setActivePower(-$ap);
  $ev.setTimestamp($cts);
  update($ev);
end 

rule "-Smappee: event ON"
when
  SmappeeEvent($id: applianceId, $ts: timestamp, $ap: activePower>0)
  SmappeeAppliance(id==$id, $name:name)
  SmappeeActuator(name==$name)
  Event(source==$name) // Linked to OR
then
  execute.command($name, "ON");
end

rule "-Smappee: event OFF"
when
  SmappeeEvent($id: applianceId, $ts: timestamp, $ap: activePower<0)
  SmappeeAppliance(id==$id, $name:name)
  SmappeeActuator(name==$name)
  Event(source==$name) // Linked to OR
then
  execute.command($name, "OFF");
end

// Below are shell execution commands which need to be executed periodically

rule "--Smappee: Exec Servicelocations.sh"
salience 10
when
  SmappeeClientCredentials($a: access_token)
  not SmappeeServiceLocation()
then
  execute.command("Servicelocations.sh", $a);
  insert(new ExecDelay("Servicelocations"));
end

rule "--Smappee: Exec ServicelocationInfo.sh"
salience 10
when
  SmappeeClientCredentials($a: access_token)
  SmappeeServiceLocation($id: serviceLocationId)
  not  SmappeeAppliance()
then
  execute.command("ServicelocationInfo.sh", $a+" "+$id);
  insert(new ExecDelay("ServicelocationInfo"));
end

rule "--Smappee: Exec Consumption1.sh"
salience 10
when
  SmappeeClientCredentials($a: access_token)
  SmappeeServiceLocation($id: serviceLocationId)
  not SmappeeConsumptions()
  not SmappeeConsumption()
then
  long now = (new Date()).getTime();
  now = (now/300000)*300000;
  long prev = now-10*60000;
  String param = $a+" "+$id+" "+prev+" "+now;
  execute.command("Consumption1.sh", param);
  insert(new ExecDelay("Consumption1"));
end

rule "--Smappee: Exec Events.sh init"
timer(int: 10s)
when
  $aps: ArrayList($size:size>0) from collect(SmappeeApplianceCopy(power==0.0))
  SmappeeClientCredentials($a: access_token)
  SmappeeServiceLocation($id: serviceLocationId)
  not ExecDelay(source=="Events")
then
  long now = (new Date()).getTime();
  String param = $a+" "+$id+" 0 "+now+" ";
  for(Object aid: $aps){
    param += "applianceId="+((SmappeeApplianceCopy)aid).getId()+"&";
  }
  param += " "+$size*2;
  execute.command("Events.sh", param);
  insert(new ExecDelay("Events"));
end

rule "--Smappee: Exec Events.sh"
timer(int:50s)
when
  SmappeeAppliances($aps: appliances)
  SmappeeClientCredentials($a: access_token)
  SmappeeServiceLocation($id: serviceLocationId)
  not ExecDelay(source=="Events")
then
  long now = (new Date()).getTime();
  long prev = now - 130000;
  String param = $a+" "+$id+" "+prev+" "+now+" ";
  for(Object aid: $aps){
    param += "applianceId="+((SmappeeAppliance)aid).getId()+"&";
  }
  param += " 10";
  execute.command("Events.sh", param);
  insert(new ExecDelay("Events"));
end

// Actuators
rule "-Smappee: Exec Actuator.sh actuator"
when
  SmappeeActuatorCopy($act: name, $aid: id)
  Event(source==$act, $v: value != "")
  SmappeeClientCredentials($a: access_token)
  SmappeeServiceLocation($id: serviceLocationId)
then
  String param = $a+" "+$id+" "+$aid+" "+$v.toString()+" 0";
  execute.command("Actuator.sh", param);
end

##See also

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.