is it possible to upload to pvoutput.org
http://pvoutput.org/list.jsp?userid=4806
Currently i use an old xp pc and upload using that, now i currently use HAH to send reports to pachube but would like to also send data to pvoutput.
anyone give us a pointer as to if it's possible?
Dean
Have you run this script manually, ie lua <scriptname>
Can you post the output, I sometimes get an error with the module command on the first line, you could try commenting that out, but without actually seeing the error it will be difficult to say what's wrong.
Karl
--module (...,package.seeall)
info = {version="1.0", description="Post to PVoutput" }
ApiKey = "2c8cd----cut----dd70ee5385"
FeedID = "29XX"
URL="http://pvoutput.org/service/r2/addoutput.jsp"
function init()
f = xap.Filter()
f:add("xap-header", "source", "dbzoo.livebox.CurrentCost:Ch.1")
f:callback(saveload)
xap.Timer(post, 60):start()
end
function saveload()
watts = xap.getValue("input.state","text")
end
function post(self)
local cmd = 'curl -d ' .. os.date("%Y%m%d ") .. watts .. " -H X-Pvoutput-ApiKey: " .. ApiKey .. " -H X-Pvoutput-SystemId: " .. FeedID .. URL
-- print(cmd)
os.execute(cmd)
local msg = string.format([[xap-header
{
target=dbzoo.livebox.CurrentCost:script
class=xAPBSC.ccel
}
input.state
{
state=on
text=%s
displaytext=%s watts
}]], watts, watts)
xap.sendShort(msg)
-- print(msg)
self:delete()
end
Well calling self:delete() in the post function means that the timer will only fire after 60 seconds and then delete itself? I'm sure this is not what you intended.
Later instead of using CURL and an OS callout you might want to check out http://w3.impa.br/~diego/software/luasocket/http.html which is built in.
Declare watt as a variable in the module before you start using it in the init() function, like you do the apikey and url -> watt=0 would be fine otherwise if the post function is executed before a callback of data has arrived you'll get an error in the POST function accessing a variable before its declared.
Also try running this as a standalone program its easier then firing up plugboard for each session, you'll need a few additional lines of code. Note for this are on the wiki and are pretty easy to follow.
Brett
To be automatically loaded they must be placed in the /etc/plugboard directory and have the prefix Applet.lua.
As documented here -> http://www.dbzoo.com/livebox/hah_plugboard_v2#writing_an_applet
Rename this file to PVoutputApplet.lua
Also you are missing the import statement
require("xap")
Which is REALLY important.
Brett
I've been working on this for a day or so now and have come up with a partly working script which will post data to PVoutput.org
This is a stand alone lua script at the moment but the intention is that it should be turned into an applet and run from the /etc/plugboard directory.
This is the script:
***************************************************************************************
-- Script to upload data to PVoutput.org from the HAH livebox
require ('xap')
require('xap.bsc')
local io = require("io")
local http = require("socket.http")
local ltn12 = require("ltn12")
watts="240"
elapsed = 0
Api = "2c8cd623b1........cut..............70ee538540"
Feed = "29xx"
url='://pvoutput.org/service/r2/addstatus.jsp?key='
function init ()
f = xap.Filter();
f:add("xap-header", "source", "dbzoo.livebox.CurrentCost:Ch.1");
f:callback(GetCurrentReading);
end
xap.init("dbzoo.lua.PVtest","FF00DD00" )
function post(self)
elapsed = elapsed + self.interval
-- print("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") .. "&v1=" ..watts)
b, c, h = http.request("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") .. "&v1=" ..watts)
if elapsed > 1 then
self:delete()
end
end
xap.Timer(post, 2):start()
print("System Starting")
function GetCurrentReading ()
local value = xap.getValue('input.state','text')
watts = value
print("watts")
end
************************************************************************
It works insofaras it will post the data using the hard coded figure for watts as set in the initialisation.
I don't know what I'm doing wrong but I can't get any of my scripts to recognise or respond to any xap messages.
The init() function doesn't appear to ever be called. I assume that I must be using the wrong syntax or something.
Obviously the self:delete is self defeating but it is there at the moment to prevent multiple posts from exceeding the
posting limit. It will be necessary to devise some way of manipulating the instantaneous figure read from the currentcost
output by dividing by 12, 6 or 4 depending on what update interval is being used (5 mins 10 mins or 15 mins) but that should
just be a matter of arithmetic once we have sorted out the running of the script.
I'd be grateful for any comments or help.
xap.process()
I've moved some lines around, just to make reading the code a little easier, functions at the start and some indents. I've tried this and it works. However, I haven't finished it for you. Brett will most definately not like it, Brett??, but it's a start. See how you get on, look at what I've done and compare it with yours, you've done a great job so far and you'll pick up a lot more by looking at example and finding out where you've gone wrong.
Keep it it, it's really good to get another person on-board to bounce ideas off, it all helps with the development of the project.
Karl
require ('xap')
require('xap.bsc')
local io = require("io")
local http = require("socket.http")
local ltn12 = require("ltn12")
watts="240"
elapsed = 0
Api = "2c8cd623b1........cut..............70ee538540"
Feed = "29xx"
url='://pvoutput.org/service/r2/addstatus.jsp?key='
function post(self)
elapsed = elapsed + self.interval
-- print("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") .. "&v1=" ..watts)
b, c, h = http.request("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") .. "&v1=" ..watts)
if elapsed > 1 then
self:delete()
end
end
function GetCurrentReading(frame)
local watts = xap.getValue("input.state","text")
print(string.format("watts = %s", tostring(watts)))
end
function init()
print("System Starting")
f = xap.Filter()
f:add("xap-header", "source", "dbzoo.livebox.CurrentCost:ch.1")
f:callback(GetCurrentReading)
end
xap.init("dbzoo.lua.PVtest","FF00DD00" )
init()
xap.process()
--xap.Timer(post, 2):start()
Good job Karl. I've done some further mods to the code and introduced a conversion factor to allow for the fact that the CC overreads. It will also be necessary to have a "floor" setting (say 50 watts) below which the information is not counted. The global variable watts is now updated by the modified output from the CC and this is appended to the string. (Currently just printed on the screed and not posted on the site yet)
All we'll need then is an agreed scheme for how to tot up the power output (perhaps an array) and come up with a figure which can be stored and posted at the appropriate time and I think that'll probably do it.
I'l probably have to have a rest from this for the rest of the day (she's getting a bit fractious). But I'll do some more next week.
Here's the modified code:
****************************************************************
require ('xap')
require('xap.bsc')
local io = require("io")
local http = require("socket.http")
local ltn12 = require("ltn12")
watts="0"
elapsed = 0
ConvFactor = 0.95
Api = "2c8cd623b19-----cut----9dd70ee538540"
Feed = "29XX"
url='://pvoutput.org/service/r2/addstatus.jsp?key='
function post(self)
elapsed = elapsed + self.interval
print("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") .. "&v1=" ..watts)
-- b, c, h = http.request("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") ..
"&v1=" ..watts)
-- if elapsed > 1 then
-- self:delete()
-- end
end
function GetCurrentReading(frame)
local nowwatts = xap.getValue("input.state","text")
print(string.format("nowwatts = %s", tostring(nowwatts)))
test=nowwatts*ConvFactor
print (string.format("ModPwr = %s", tostring(test)))
watts=test
end
function init()
print("System Starting")
f = xap.Filter()
f:add("xap-header", "source", "dbzoo.livebox.CurrentCost:ch.1")
f:callback(GetCurrentReading)
end
xap.init("dbzoo.lua.PVtest","FF00DD00" )
init()
xap.Timer(post, 60):start()
xap.process()
***************************************************************************
Hi,
not sure if this is what you are talking about or not but I have a script that tots up the total energy usage in 5 minutes intervals then add this 5 min total to a file located on the HAH to give a running cumulative total (the benefit of this is that rebooting the HAH only looses a max of 5min data).
I post this to pachube but you could post elsewhere as per your script. I reset this cumulatvie total by zeroing the file at midnight to give me a daily power usage but again you could reset it via a timer as often as you like.
I am sure my script is not written brilliantly but it works and may give you some ideas.
For info it works as follows:
The powerlog function populates the CurrentKwH variabe with the usage in kwH since the last value reported by current cost, then adds this to the TempCumulativeKwH variable held in memory. The power variable then gets updated with the most recent instantaneos value for to use during the next period.
every five minutes the PowerSave function is loaded which opens the /etc/plugboard/CumulativeKwH file and adds the TempCumulativeKwH value from memory to it and then overwrites the file. it then resets the timer and posts via pachube using the CumualtiveDataPost function (this is where you would post to PVoutput, etc)
Note: you may have to initially manually add the log file (/etc/plugboard/CumulativeKwH) to the HAH as I dont think the script will automatically make it.
Script is here:
-- collect cumulative power data and log to pachube
module(...,package.seeall)
require("xap")
require("string")
info={
version="1.0", description="Cumulative Electric Script"
}
local Power = 1
local Logtime = os.time()
local TempCumulativeKwH = 0
CumulativeKwH = 0
local CurrentKwH = 0
function powersave(self)
local file = io.open("/etc/plugboard/CumulativeKwH","r")
CumulativeKwH = file:read("*all")
file:close()
CumulativeKwH = tonumber(CumulativeKwH) + TempCumulativeKwH
TempCumulativeKwH = 0
local cmd = string.format("echo '%s'>/etc/plugboard/CumulativeKwH", CumulativeKwH)
os.execute(cmd)
self:reset()
CumulativeDataPost()
end
function powerlog()
local CurrentPeriod = os.difftime(os.time(), Logtime)
Logtime = os.time()
local CurrentKwH = Power * CurrentPeriod / 3600000
TempCumulativeKwH = TempCumulativeKwH + CurrentKwH
Power = xap.getValue("input.state","text")
end
function CumulativeDataPost()
CumulativeData = string.format([[xap-header
{
class=pachube.update
target=dbzoo.livebox.pachube
}
datastream
{
id=10
tag=Electric KwH
Value=%s
}]], CumulativeKwH)
xap.sendShort(CumulativeData)
end
function init()
local f = xap.Filter()
f:add("xap-header","source","dbzoo.livebox.CurrentCost:ch.1")
f:add("xap-header","class","xAPBSC.event")
f:callback(powerlog)
xap.Timer(powersave, 300):start()
end
All you need to do extra is to reset the file to zero as and when you require. I do this by scripting the following at midnight but it could be done with a standard timer function
local cmd = string.format("echo '0'>/etc/plugboard/CumulativeKwH")
os.execute(cmd)
Hope its of some use
Garry
xap.getValue() will be deprecated at some point in time, it was only put in so that moving from V1 -> V2 would be less work. At some point your script will break when I remove backward V1 support.
For a Filter callback your function should look like this.
function GetCurrentReading(frame)
local watts = frame:getValue("input.state","text")
end
The frame is the XAP message parsed into pieces what you want to do is call a method on this frame object. Do consult the API reference page on this: http://www.dbzoo.com/livebox/hah_plugboard_v2#frame
Brett
In the spirit of not reinventing the wheel I think that your code could be the basis for a PVoutput plugboard app. I have a look in the next couple of days and see what can be done.
Thanks for the advice. As I posted somewhere else it's a pretty steep learning curve. All help and pointers gratefully received!
OK I think I have a working script for posting live data to PVoutput.org direct from the HAH livebox using the CurrentCost data. Many thanks to Garry (garrydwilms) who will no doubt recognise some of his code in the attached script.
Currently it is formatted as a standalone script while I do some testing but it should be easy enough to convert to a plugboard applet. I'd be interested to hear from anyone who cares to test it out.
It will need some modifications because of the way that the CC meter overreads PV output but that can be dealt with later.
I'm sure that there is a way of attaching the script as a file, but da**ed if I can find it. So here it is longhand:
***************************************************************************
require ('xap')
require('xap.bsc')
require("string")
local io = require("io")
local http = require("socket.http")
local ltn12 = require("ltn12")
CurrentTemp = 0
Logtime = os.time()
TempCumulativeKwH = 0
CumulativeKwH = 0
CurrentKwH = 0
watts = 0
elapsed = 0
ConvFactor = 0.95
Api = "2c8c----cut-----ee538540" -- put your PVoutput api key here
Feed = "29XX" -- put your PVoutput feed ID here
Postinterval = 5 -- The number of minutes between posts to PVoutput
url='://pvoutput.org/service/r2/addstatus.jsp?key='
Power = 1
function post(self)
local ckwh = math.floor(CumulativeKwH *1000 )
if CumulativeKwH ~= 0 then
b, c, h = http.request("http" ..url ..Api .. "&sid="..Feed .. "&d=" ..os.date("%Y%m%d") .. "&t=" ..os.date("%H:%M") ..
"&v1=" ..ckwh.. "&v2=" ..Power .."&v5=" ..CurrentTemp)
end
end
function powersave(self)
local file = io.open("/etc/plugboard/CumulativeKwH","r")
CumulativeKwH = file:read("*all")
file:close()
CumulativeKwH = tonumber(CumulativeKwH) + TempCumulativeKwH
TempCumulativeKwH = 0
local cmd = string.format("echo '%s'>/etc/plugboard/CumulativeKwH", CumulativeKwH)
os.execute(cmd)
self:reset()
post()
end
function GetTemp(frame)
CurrentTemp = frame:getValue("input.state","text")
end
function powerlog(frame)
local CurrentPeriod = os.difftime(os.time(), Logtime)
Logtime = os.time()
local CurrentKwH = Power * CurrentPeriod / 3600000
TempCumulativeKwH = TempCumulativeKwH + CurrentKwH
Power = frame:getValue("input.state","text")
if tonumber(Power) < 45 then
Power = 0
end
end
function init()
local f = xap.Filter()
f:add("xap-header", "source", "dbzoo.livebox.CurrentCost:ch.1")
f:add("xap-header","class","xAPBSC.event")
f:callback(powerlog)
local f = xap.Filter()
f:add("xap-header", "source", "dbzoo.livebox.CurrentCost:temp")
f:add("xap-header","class","xAPBSC.event")
f:callback(GetTemp)
end
xap.init("dbzoo.lua.PVtest","FF00DD00" )
init()
xap.Timer(powersave, Postinterval*60):start()
xap.process()
****************************************************************************
Hi Dean,
It should be possible to send the data you want to pvoutput using their service api, http://pvoutput.org/help.html#api. There are some sample Lua scripts that show you how to integrate http requests into Lua in the /etc/plugboard/samples folder on the HAH.
The way I would approach this would be to get the correct http post/get command working from a browser and then transfer that to Lua,
Karl