is it possible to upload to pvoutput.org

17 replies [Last post]
g7pkf
Offline
United Kingdom
Joined: 11 Jan 2011

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

BoxingOrange
Offline
United Kingdom
Joined: 11 Jun 2010
PVOutput Update

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

g7pkf
Offline
United Kingdom
Joined: 11 Jan 2011
not good at scripts but a friend tried

This is the code but it does not work, done by a friend who is trying to join forum...

 

can someone take a butchers and see if they can see anything glaringly obviously wrong?

 

The following doesn't work but is my first stab at trying to construct a lua applet to do the job

 

 

**************************************

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

 

 

***************************************************************************

BoxingOrange
Offline
United Kingdom
Joined: 11 Jun 2010
Manual Testing

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

BoxingOrange
Offline
United Kingdom
Joined: 11 Jun 2010
Try this....

--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

brett
Offline
Providence, United States
Joined: 9 Jan 2010
A few comments

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

g7pkf
Offline
United Kingdom
Joined: 11 Jan 2011
dunno all double dutch to me but heres the output :)

brett
Offline
Providence, United States
Joined: 9 Jan 2010
That won't load as an Applet

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

allanayr
Offline
Ayr, United Kingdom
Joined: 25 Sep 2011
Posting to PVoutput

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()

BoxingOrange
Offline
United Kingdom
Joined: 11 Jun 2010
I've moved some lines around,

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()

allanayr
Offline
Ayr, United Kingdom
Joined: 25 Sep 2011
Great work Karl

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()

***************************************************************************

garrydwilms
Offline
United Kingdom
Joined: 31 Mar 2011
current cost data cumulation

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

brett
Offline
Providence, United States
Joined: 9 Jan 2010
xap.getValue is not the right call (even thou it works)

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

allanayr
Offline
Ayr, United Kingdom
Joined: 25 Sep 2011
Thanks Garry

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.

allanayr
Offline
Ayr, United Kingdom
Joined: 25 Sep 2011
Thanks

Thanks for the advice. As I posted somewhere else it's a pretty steep learning curve. All help and pointers gratefully received!

allanayr
Offline
Ayr, United Kingdom
Joined: 25 Sep 2011
Posting to PVoutput.org

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()

****************************************************************************

g7pkf
Offline
United Kingdom
Joined: 11 Jan 2011
email me it and i will put it on my webserver for easy access

email me it and i will put it on my webserver for easy access

g7pkf
Offline
United Kingdom
Joined: 11 Jan 2011
Working fine :)

Been using for a couple of days now and it seems to work fine.

And i now have my plugboard applets working.

 

thanks for writing this script appreciated.

Hardware Info