Has anyone incorporated a Rainforest EAGLE™ Energy Access Gateway Link to Ethernet
with REST API or the USB Raven into OpenHAB. I’m looking to get one but I want to figure out what will be the easiest to implement to monitor my smart meter. documentation can be found HERE
I have one of these, the code below isn’t preity, as I wrote it a while back, but it’ll get you started. I can’t test it atm as PG&E just swapped out my SmartMeter for some reason and I need to pair the Eagle with the new device.
Here are my Items:
Number HousePowerInstant "SmartMeter Power [%.3f]" (GMonitorPower,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)
Here’s the Rule to drive it…
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 = "0xe1e100000e1e10"
val String EAGLE_URL = "http://192.168.1.13/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
I am looking at the rainforest products as well.
I assume this rule will only work with the Eagle due to its network connection? The Raven presumably can’t be accessed over usb using a modification of this script?
Cheers
The Raven exposes an XML API:
but it’d be easy enough to hand-translate. The Eagle exposes that API, as well as the one it’s UI uses (which is what I’m using here) which has JSON and XML.
Thanks Mark.
I’ll probably get the Eagle and use your code as a starting point.
Cheers!
I purchased the eagle end set it up one thing I had to do was disable the security to make it work.
In the web portal click the down arrow next to date.
at the bottom of that page click the gear.
uncheck the security box.
Hope this helps.
It would be nice if we could combine all this information under the Application Integration section of the wiki.
Feel free to add a page there, it’s open to community members to create/update.
done
One thing I noticed is sometimes I miss the consumption update even with the cron set to every 30seconds.
What if openHAB had a listener for the updates posted from the eagle.
my eagle is on the way, looking forward to getting my hands on my data…
It’s possible I have the logic somewhat amiss. In general, you only see periodic updates to the values, based upon how often the SmartMeter itself publishes the changes.
In the middle, if you call the API, it really just returns the last known (absolute) values.
I use this as a backup for my Brultech setup, so I haven’t spent a ton of time tuning it.
I was mistaken it stores the consumed number till you pole. I noticed this phenomenon when my eagle was disconnected for a bit then when it did connect the consumed was a total of consumption from that last read and was much greater that the normal 1 min read.
I believe
var float used = currDelivered - lastDelivered
it just generating the demand for each reported read.
is there a way to have these totals for last hour and day?
like a cron that records current delivered at midnight then have it compare that number on every reported read.
for last hour though I’m not sure. I use mysql is there a way to read it for an hour back and compare with that.
EDIT I have the midnight read figured out… i think.
I added this rule. Now I just need to figure out how to read that and subtract current from it to make daily running total
rule "Set Data from Eagle at midnight"
when
Time is midnight
then
postUpdate(HouseEnergyDeliveredMidnight, lastDelivered)
end
found an interesting line in the persistence demo
Weather_Temperature.historicState(now.minusMinutes(2), "mysql")
one thing I am having a problem with is getting the float out of a number item. this seems to be workig but the last number is dissapearing. if the eagle reads 15896.321 but it’ll get written to the item as 15696.350.
var float day = currDelivered - (HouseEnergyDeliveredMidnight.state as DecimalType).floatValue()
Thank you for posting this. I’ve been playing with the cloud API (I’m a beginner) on and off during Dec/Jan. Question - I tried to use it tonight and I get an Error message “Bad Data <>”. Any thoughts/feedback on what I’m doing incorrectly? I changed the IP address and device ID to match my device. Help? Thanks.
With that message will be the source JSON data that contains the bad data.
This might be as simple as a value like "nan"
(not a number) that the Eagle emits when it can’t contact the SmartMeter.
You’ll want to post the full log line.
I realized since I am not producing electricity at my home I could simplify the rule.
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()
logInfo("eagle", String::format("Energy %s demand=%.3f delivered=%.3f", currTimestamp.toString, currDemand, currDelivered))
postUpdate(HouseMeterRead, currDelivered)
postUpdate(HouseEnergyDay, day * 100)
}
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
Hi,
Full log line. Is this what you meant?
2016-03-02 20:25:46.269 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model ‘kozo.rules.rules’
2016-03-02 20:26:00.410 [ERROR] [org.openhab.model.script.eagle] - Bad Data {}
2016-03-02 20:26:00.473 [INFO ] [org.openhab.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 403ms
2016-03-02 20:27:00.282 [ERROR] [org.openhab.model.script.eagle] - Bad Data {}
2016-03-02 20:27:00.282 [INFO ] [org.openhab.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 281ms
2016-03-02 20:28:00.266 [ERROR] [org.openhab.model.script.eagle] - Bad Data {}
2016-03-02 20:28:00.266 [INFO ] [org.openhab.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 265ms
2016-03-02 20:29:00.256 [ERROR] [org.openhab.model.script.eagle] - Bad Data {}
2016-03-02 20:29:00.256 [INFO ] [org.openhab.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 249ms
I’ve tried to run the URL (http:///cgi-bin/cgi_manager) in a browser and I get the { } response there as well. I also tried to run this URL in Postman to see if I could get a response but no difference (this is again on the eagle directly, not the cloud).
I have shut off security and I am also able to bring up the energy meter results with the standard URL:
http:///htdocs/emu/meter.html?mac_id=
Welcome any thoughts…Thank you for your support.
try adding the code
logInfo("eagle", result)
after
var result = sendHttpPostRequest(EAGLE_URL, "application/x-www-form-urlencoded", postData)
like mine to see what the eagle is returning.
here is an example of what mine returns.
2016-03-03 13:49:30.441 [INFO ] [org.openhab.model.script.eagle] - {"meter_status":"Connected",
"demand":"1.0870",
"demand_units":"kW",
"demand_timestamp":"1457012973",
"summation_received":"0.000",
"summation_delivered":"166566.550",
"summation_units":"kWh",
"price":"0.0940",
"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":"12.749000",
"threshold_lower_demand":"-2.000000",
"fast_poll_frequency":"0x00",
"fast_poll_endtime":"0x00000000"}
2016-03-03 13:49:30.805 [INFO ] [org.openhab.model.script.eagle] - PERF Pull-Data-from-Eagle elapsed: 722ms