Rainforest Zigbee Smart Meter support

rainforest
energy
zigbee
Tags: #<Tag:0x00007f0146dbd000> #<Tag:0x00007f0146dbce98> #<Tag:0x00007f0146dbcd08>

(Mark Clark) #21

Double-check that the MAC Address is correctly specified in:

                val String EAGLE_MAC = "0xd8d5b90000???????"

This string must match the details from your specific Eagle unit, or the call will result in the “Bad Data” message being output.

My “Bad Data” String is different as it can no longer contact the SM it’s attached to. There’s data from the unit with the specified MAC, and the overall format is correct:

21:06:01.184 ERROR org.openhab.model.script.eagle[:83]- Bad Data {“meter_status”:“Rejoining”, “demand”:“nan”, “demand_units”:“kW”, “demand_timestamp”:“946684800”, “summation_received”:“nan”, “summation_delivered”:“nan”, “summation_units”:“kWh”, “price”:"-1.0000", “price_units”:“65535”, “message_timestamp”:“946684800”, “message_confirmed”:“N”, “message_confirm_required”:“N”, “message_id”:“0”, “message_queue”:“cancelled”, “message_read”:“Y”, “threshold_upper_demand”:“29.206000”, “threshold_lower_demand”:"-5.837000", “fast_poll_frequency”:“0x00”, “fast_poll_endtime”:“0x00000000”}

With nothing in the “{}” I’d guessing the MAC used isn’t correct or, potentially, something else is attached to the Eagle that’s preventing it from responding correctly.


(Keith Kozo) #22

Solved: Ok - figured it out. Mark - you were right. It was the device ID. I did not have the “0x” in front of the device ID. I figured this out by going to the device web server and noting that device ID it was querying. 18 characters…

Thanks for your help! Now to figure out how to chart/see the energy data!


(Mark Clark) #23

It’s always the small things that get you when configuring these components :wink:

Glad you got it going in the end!

If there’s something that can be added to the Wiki page for the next user, feel free to go ahead add details to it directly.


(Keith Kozo) #24

Hi,
Next question - the rule is running but after a few minutes it throws the following error. I see something above about the ‘HouseEnergyDeliveredMidnight’ but I could not determine if that was a fix?

Thoughts? Thanks!

2016-03-05 20:52:01.520 [ERROR] [.o.m.r.i.engine.ExecuteRuleJob] - Error during the execution of rule Pull Data from Eagle
java.lang.RuntimeException: The name ‘HouseEnergyDeliveredMidnight’ cannot be resolved to an item or type.


(Mark Lavercombe) #25

You need to make an item called HouseEnergyDeliveredMidnight so that error goes.


(Keith Kozo) #26

Ah - I thought I had tried that. I reconfigured and it works! Should we update the “items” in the wiki to reflect this?

Item File:
Number HousePowerInstant “SmartMeter Power [%.0f]” (GMonitorPower,GPersist)
Number HouseMeterRead “SmartMeter Energy Delivered [%.3f]” (GMonitorEnergy,GPersist)
Number HouseEnergyDay “SmartMeter Energy Delivered [%.3f]” (GMonitorEnergy,GPersist)
Number HouseEnergyDelivered “SmartMeter Energy Delivered [%.3f]” (GMonitorEnergy,GPersist)
Number HouseEnergySent “SmartMeter Energy Sent [%.3f]” (GMonitorEnergy,GPersist)
Number HouseEnergyPrice “SmartMeter Energy Price [%.3f]” (GMonitorEnergy,GPersist)
Number HouseEnergyCost “SmartMeter Energy Cost [%.3f]” (GMonitorEnergy,GPersist)
Number HouseEnergyDeliveredMidnight “SmartMeter Energy Cost [%.0f]” (GMonitorEnergy,GPersist)

Another question: I only receive data on one item that I really wanted, HousePowerInstant. Does anyone else use any of the other data for any interesting charts/switches etc.? Thanks!


(David Luther) #27

Currently I only use the 2 items for chart HousePowerInstant and HouseEnergyDay but I plan on adding items for cost last hour and day using persist. The reason I have day only multiplied by 100 instead of 1000 is it made my chart to hard to read but it still gives a good view of consumption when viewed in graph. The graph below is for 3 days.

here is the link I use to get higher resolution graphing. (minus my public IP of course)

http://000.000.000.000:8909/chart?period=3D&h=800&w=10700&service=mysql&items=HouseEnergyDay,HousePowerInstant

here is a month chart when I first had the day set to 1000 you can see the deference in charting.


(Steve M.) #28

Anyone using the Rainforest Smart Meter with OH2?

I added the items and rule to my installation. It appears the data is being read from the meter however I get the following openhab.log entries:

2016-07-24 15:57:00.332 [WARN ] [.core.transform.TransformationHelper] - Cannot get service reference for transformation service of type JSONPATH
2016-07-24 15:57:00.333 [WARN ] [ore.transform.actions.Transformation] - No transformation service 'JSONPATH' could be found.
2016-07-24 15:57:00.341 [ERROR] [eclipse.smarthome.model.script.eagle] - Bad Data {"meter_status":"Connected", "demand":"12.8640", "demand_units":"kW", "demand_timestamp":"1469375816", "summation_received":"0.000", "summation_delivered":"111125.195", "summation_units":"kWh", "price":"0.1100", "price_units":"840", "price_label":"Set by User", "message_timestamp":"946684800", "message_confirmed":"N", "message_confirm_required":"N", "message_id":"0", "message_queue":"active", "message_read":"Y", "threshold_upper_demand":"25.136000", "threshold_lower_demand":"-2.000000", "fast_poll_frequency":"0x00", "fast_poll_endtime":"0x00000000"} 
2016-07-24 15:57:00.352 [INFO ] [eclipse.smarthome.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 330ms

I’ve read others have seen this issue due to library entries missing in the rule but OH2 isn’t supposed to need library entries (although I did add them just to troubleshoot).

Any suggestions?


(Steve M.) #29

OK, never mind I figured out the problem (newbie issue).

I added “jsonpath” to the OH2 addons.cfg file under “transformation=” line. I also had to add the import information back into the rule before it would work, but it does seem to be working now.

Thank you!


(Steve M.) #30

@guessed

Any ideas what might be causing the following error from my rule (using OpenHAB2)?

2016-12-26 19:45:01.087 [ERROR] [ore.transform.actions.Transformation] - Error executing the transformation 'JSONPATH': the given parameters 'JSonPath' and 'source' must not be null
2016-12-26 19:45:01.094 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule Pull Data from Eagle: cannot invoke method public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String) on null

It seems as though all my data is pulling correctly but these two errors consistently pop up every few seconds.

2016-12-26 19:48:30.468 [INFO ] [eclipse.smarthome.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 403ms
2016-12-26 19:49:00.359 [INFO ] [eclipse.smarthome.model.script.eagle] - {"meter_status":"Connected",
"demand":"2.4030",
"demand_units":"kW",
"demand_timestamp":"1482781736",
"summation_received":"0.000",
"summation_delivered":"124283.899",
"summation_units":"kWh",
"price":"0.1300",
"price_units":"840",
"price_label":"Set by User",
"message_timestamp":"946684800",
"message_confirmed":"N",
"message_confirm_required":"N",
"message_id":"0",
"message_queue":"active",
"message_read":"Y",
"threshold_upper_demand":"25.885000",
"threshold_lower_demand":"-2.000000",
"fast_poll_frequency":"0x00",
"fast_poll_endtime":"0x00000000"}

My rule is verbatim from the wiki with the addition of the “HouseEnergyDeliveredMidnight” rule appended to the end:

import org.openhab.core.library.types.*
import java.lang.Float
import java.lang.Long
import org.joda.time.DateTime

var DateTime lastTimestamp = null
var float lastDelivered
var float lastReceived

rule "Pull Data from Eagle"
  when
    Time cron "0 0-59 * * * ?"
  then
          var t = now
    val String EAGLE_MAC = "0xd8d5b90000001340"
    val String EAGLE_URL = "http://192.168.1.4/cgi-bin/cgi_manager"

    var String postData = String::format("<LocalCommand>
  <Name>get_usage_data</Name>
  <MacId>%s</MacId>
</LocalCommand>", EAGLE_MAC, EAGLE_MAC)

    var result = sendHttpPostRequest(EAGLE_URL, "application/x-www-form-urlencoded", postData)
    logDebug("eagle", result)
       
    try {
      var long timestamp = Long::parseLong(transform("JSONPATH", "$.demand_timestamp", result))
      var DateTime currTimestamp = new DateTime(timestamp * 1000)
      var float price = Float::parseFloat(transform("JSONPATH", "$.price", result))
      var float currDemand = Float::parseFloat(transform("JSONPATH", "$.demand", result))
      var float currDelivered = Float::parseFloat(transform("JSONPATH", "$.summation_delivered", result))
      var float currReceived = Float::parseFloat(transform("JSONPATH", "$.summation_received", result))
  
      postUpdate(HousePowerInstant, currDemand * 1000)

      if (lastTimestamp != null && !lastTimestamp.equals(currTimestamp)) {
        var float used = currDelivered - lastDelivered
        var float sent = currReceived - lastReceived

        logDebug("eagle", String::format("Energy %s demand=%.3f received=%.3f delivered=%.3f", currTimestamp.toString,
          currDemand, used, sent))
        postUpdate(HouseEnergySent, sent * 1000)
        postUpdate(HouseEnergyDelivered, used * 1000)
        postUpdate(HouseEnergyCost, (used - sent) * 1000 * price)
      }

      postUpdate(HouseEnergyPrice, price)

      lastDelivered = currDelivered
      lastReceived = currReceived
      lastTimestamp = currTimestamp  
    } catch (NumberFormatException nfe) {
      logError("eagle", "Bad Data " + result.replaceAll("\n", " "))
    }
    var long x = now.getMillis - t.getMillis
    logInfo("eagle", "PERF Pull-Data-from-Eagle elapsed: " + String::valueOf(x) + "ms")
end

rule "Set Data from Eagle at midnight"
  when
    Time is midnight
  then
    postUpdate(HouseEnergyDeliveredMidnight, lastDelivered)
end

(Mark Clark) #31

I’d guess that some number of the HTTP POST operations are failing, and getting null as a result.

The code doesn’t guard against this. Not sure why they’d fail that often though, unless there’s a network connectivity issue.

When was the last time the Eagle itself was power cycled?


(David Luther) #32

Do you have a system that is generating power? if not the parts in the rule for received can be turned off.

This is what mine currently looks like.

import org.openhab.core.library.types.*
import java.lang.Float
import java.lang.Long
import org.joda.time.DateTime

var DateTime lastTimestamp = null
var float lastDelivered

rule "Pull Data from Eagle"
  when
    Time cron "*/30 * * * * ?"
  then
          var t = now
    val String EAGLE_MAC = "0xd8d5b90000005aeb"
    val String EAGLE_URL = "http://192.168.0.109/cgi-bin/cgi_manager"

    var String postData = String::format("<LocalCommand>
  <Name>get_usage_data</Name>
  <MacId>%s</MacId>
</LocalCommand>", EAGLE_MAC, EAGLE_MAC)

    var result = sendHttpPostRequest(EAGLE_URL, "application/x-www-form-urlencoded", postData)
    //	logInfo("eagle", result)
       
    try {
      var long timestamp = Long::parseLong(transform("JSONPATH", "$.demand_timestamp", result))
      var DateTime currTimestamp = new DateTime(timestamp * 1000)
      var float currDemand = Float::parseFloat(transform("JSONPATH", "$.demand", result))
      var float currDelivered = Float::parseFloat(transform("JSONPATH", "$.summation_delivered", result))
  
      postUpdate(HousePowerInstant, currDemand * 1000)

      if (lastTimestamp != null && !lastTimestamp.equals(currTimestamp) && !currDelivered.equals(lastDelivered)) {
		var float day = currDelivered - (HouseEnergyDeliveredMidnight.state as DecimalType).floatValue()
		var float month = currDelivered - (HouseEnergyDeliveredBill.state as DecimalType).floatValue()
        logInfo("eagle", String::format("Energy %s demand=%.3f delivered=%.3f", currTimestamp.toString, currDemand, currDelivered))
		postUpdate(HouseMeterRead, currDelivered)
		postUpdate(HouseEnergyDay, day)
		postUpdate(HouseEnergyMonth, month)
      }


      lastDelivered = currDelivered
      lastTimestamp = currTimestamp  
    } catch (NumberFormatException nfe) {
      logError("eagle", "Bad Data " + result.replaceAll("\n", " "))
    }
    var long x = now.getMillis - t.getMillis
    logInfo("eagle", "PERF Pull-Data-from-Eagle elapsed: " + String::valueOf(x) + "ms")
end
rule "Set Data from Eagle at midnight"
  when
    Time is midnight
  then
    postUpdate(HouseEnergyDeliveredMidnight, lastDelivered)
end

(Steve M.) #33

I cycled the power and the Eagle and I gave @LeXLuther422 code a try (removing the “sent” data), same results.

I also have this error as well as the two posted above

2016-12-27 18:51:01.035 [ERROR] [.smarthome.model.script.actions.HTTP] - Fatal transport error: java.util.concurrent.TimeoutException

All three errors fire off together every minute or so.


(Mark Clark) #34

If you’re seeing messages every minute, then it’s always failing. In this case, it would be worthwhile checking that the Eagle si still at the original IP address.

You can test connectivity to it, from a terminal shell on your openHAB installation, by doing something akin to:

telnet 192.168.1.4 80

If you don’t get a response like

Connected..

Then there’s some problem with the device, or its changed its IP address.


(Steve M.) #35

No issues connecting via http or telnet. The rule works but my log fills up with the 3 error messages.


(Steve M.) #36

Ok, I fixed two of the three errors.

These two errors are now fixed:

2016-12-26 19:45:01.087 [ERROR] [ore.transform.actions.Transformation] - Error executing the transformation 'JSONPATH': the given parameters 'JSonPath' and 'source' must not be null
2016-12-26 19:45:01.094 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule Pull Data from Eagle: cannot invoke method public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String) on null

I added “.toString” to the “postData” and “result” data strings.


    var result = sendHttpPostRequest(EAGLE_URL, "application/x-www-form-urlencoded", postData.toString)
    //	logInfo("eagle", result)
       
    try {
      var long timeStamp = Long::parseLong(transform("JSONPATH", "$.demand_timestamp", result.toString))
      var DateTime currTimestamp = new DateTime(timeStamp * 1000)
      var float price = Float::parseFloat(transform("JSONPATH", "$.price", result.toString))
      var float currDemand = Float::parseFloat(transform("JSONPATH", "$.demand", result.toString))
      var float currDelivered = Float::parseFloat(transform("JSONPATH", "$.summation_delivered", result.toString))

I still have this error:

2016-12-27 18:51:01.035 [ERROR] [.smarthome.model.script.actions.HTTP] - Fatal transport error: java.util.concurrent.TimeoutException

UPDATE:
I fixed the last error, reference “add optional timeout parameter to sendHttp*Request #2565” by adding a timeout integer to the following line:

    var result = sendHttpPostRequest(EAGLE_URL, "application/x-www-form-urlencoded", postData.toString, 3000)

(Mark Clark) #37

I wonder what changed in OH2 to make the original code incompatible…


(Graham Knights) #38

Does anyone have this working under OH2.2? Would be awesome to get this added as a binding!


(David Luther) #39

I moved it over to node-red. Polling the eagle the putting the data to mqtt. let me know if you would like the flow.


(Graham Knights) #40

Cool, that would be awesome. I’m new to OH (coming from SmartThings) and haven’t gone into MQTT yet but looks like I’ve got a few other things to add later that will be using MQTT as well.

Cheers!