Integration Service not working for Powerwall SW Ver. 20.49.0

Thanks to trying this, did you get a token back? Please post the response and redact your token.

i did, yes, i redacted it but didn’t post since i wasn’t sure if you needed it:

Set-Cookie: AuthCookie=<a_cookie (looks like base64)>; Path=/

Set-Cookie: UserRecord=<more stuff, but no trailing ==, maybe not base64>; Path=/

Date: Wed, 10 Feb 2021 01:57:46 GMT

Content-Length: 243

Content-Type: text/plain; charset=utf-8

{"email":"","firstname":"Tesla","lastname":"Energy","roles":["Home_Owner"],"token":"<base64 token>","provider":"Basic","loginTime":"2021-02-09T17:57:46.479577511-08:00"}

Great, now try -

curl -k -H "Authorization: Bearer <base64 token>" https://192.168.xxx.xxx/api/meters/aggregates

Running without the token would give the current error.

…/aggregates

{“code”:401,“error”:“token contains an invalid number of segments”,“message”:“Invalid m2m/bearer token”}

Usually means the token is invalid, there shouldn’t be any < > in the token

"Authorization: Bearer OgiGHjoNvwx17SRIaYFIOWPJSaKBYwmMGc5K4tTz57EziltPYsdtjU_DJ08tJqaWbWjTuI3fa_8QW32ED5zg1A=="

Bit of topic, but hope this helps - makeshift py script just to keep things updated until problem is solved. Using python implementation of the Powerwall API https://github.com/jrester/tesla_powerwall and parts from @ekul_135 's Powerwall2PVOutput
Works with the firmware 20.49.0
! Please verify the mapping of extended parameters to your PVOutput system

from tesla_powerwall import Powerwall
from tesla_powerwall import MeterType
from tesla_powerwall import API
import os
import datetime
import time
import urllib
import http.client
import ssl
import sys
import logging
from logging.handlers import RotatingFileHandler
from logging import handlers

log_file = "pw2pvo.log"
pvo_host= "pvoutput.org"
pvo_key = "<your PVOutput System key>"
pvo_sysid = "<your PVOutput System ID>"
pwemail = "<Your Powerwall Customer Email>"
pwpass = "<Your Powerwall Customer Password>"
powerwall = Powerwall("<Your Powerwall IP>")

log = logging.getLogger('')
log.setLevel(logging.INFO)
format = logging.Formatter("%(asctime)s - %(message)s")
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)
fh = handlers.RotatingFileHandler(log_file, maxBytes=(1048576*5), backupCount=1)
fh.setFormatter(format)
log.addHandler(fh)
logger = logging.getLogger(__name__)
logger.info('Start Test')

if (not os.environ.get('PYTHONHTTPSVERIFY', '') and getattr(ssl, '_create_unverified_context', None)):
    ssl._create_default_https_context = ssl._create_unverified_context

class Connection():
    def __init__(self, api_key, system_id, host):
        self.host = host
        self.api_key = api_key
        self.system_id = system_id

    def get_status(self, date=None, time=None):
        path = '/service/r2/getstatus.jsp'
        params = {}
        if date:
            params['d'] = date
        if time:
            params['t'] = time
        params = urllib.urlencode(params)
        response = self.make_request("GET", path, params)
        if response.status == 400:
            # Initialise a "No status found"
            return "%s,00:00,,,,,,," % datetime.datetime.now().strftime('%Y%m%d')
        if response.status != 200:
            raise StandardError(response.read())
        return response.read()

    def add_status(self, date, time, energy_exp=None, power_exp=None, energy_imp=None, power_imp=None, temp=None, voltage=None, battery=None, home=None, soc=None, gird=None, frequency=None, solar=None, cumulative=False):
        path = '/service/r2/addstatus.jsp'
        params = {
                'd': date,
                't': time
                }
        if energy_exp:
            params['v1'] = energy_exp
        if power_exp:
            params['v2'] = power_exp
        if energy_imp:
            params['v3'] = energy_imp
        if power_imp:
            params['v4'] = power_imp
        if temp:
            params['v5'] = temp
        if voltage:
            params['v6'] = voltage
        if battery:
            params['v7'] = battery
        if home:
            params['v8'] = home
        if soc:
            params['v11'] = soc    
        if gird:
            params['v10'] = gird
        if frequency:
            params['v9'] = frequency
        if solar:
            params['v12'] = solar    
        if cumulative:
            params['c1'] = 1
        params = urllib.parse.urlencode(params)
        response = self.make_request('POST', path, params)
        if response.status == 400:
            raise ValueError(response.read())
        if response.status != 200:
            raise StandardError(response.read())
    
    def make_request(self, method, path, params=None):
        conn = http.client.HTTPConnection(self.host)
        headers = {
                'Content-type': 'application/x-www-form-urlencoded',
                'Accept': 'text/plain',
                'X-Pvoutput-Apikey': self.api_key,
                'X-Pvoutput-SystemId': self.system_id
                }
        conn.request(method, path, params, headers)
        return conn.getresponse()


# Identify the powerwall version
powerwall.detect_and_pin_version()
print("Detected and pinned version: {}".format(powerwall.get_pinned_version()))
if powerwall.is_authenticated():
    logger.info("Logged in")
else:
    powerwall.login(pwemail, pwpass)
logger.info("Authenticated to Powerwall")

api=powerwall.get_api()

while True:
    try:
        aGirdPower=[]
        aHomePower=[]
        aHomeVoltage=[]
        aHomeFrequency=[]
        aSolarPower=[]
        aBatteryPower=[]
        aBatteryCharge=[]
        i=0
        while i<60:      
            soe=api.get_system_status_soe()
            pwm=api.get_meters_aggregates()
            aGirdPower.append(pwm['site']['instant_power'])
            aHomePower.append(pwm['load']['instant_power'])
            aHomeVoltage.append(pwm['load']['instant_average_voltage'])
            aHomeFrequency.append(pwm['load']['frequency'])
            aSolarPower.append(pwm['solar']['instant_power'])
            aBatteryPower.append(pwm['battery']['instant_power'])
            aBatteryCharge.append(soe['percentage'])
            i=i+1
            time.sleep(5)
        if len(aHomePower)>0:
            GirdPower=sum(aGirdPower,0.00)/len(aGirdPower)
            HomePower=sum(aHomePower,0.00)/len(aHomePower)
            HomeVoltage=sum(aHomeVoltage,0.00)/len(aHomeVoltage)
            HomeFrequency=sum(aHomeFrequency,0.00)/len(aHomeFrequency)
            SolarPower=sum(aSolarPower,0.00)/len(aSolarPower)
            BatteryPower=sum(aBatteryPower,0.00)/len(aBatteryPower)
            BatteryCharge=sum(aBatteryCharge,0.00)/len(aBatteryCharge)
            print(HomePower,HomeVoltage,HomeFrequency)
            print(SolarPower)
            print(GirdPower)
            print(BatteryPower,BatteryCharge)
            if SolarPower<0 :
                HomePower=HomePower-SolarPower
                SolarPower=0
            sdate=datetime.datetime.now()
            pvoDate=sdate.strftime("%Y%m%d")
            pvoTime=sdate.strftime("%H:%M")
            logger.info(str(pvoDate)+","+str(pvoTime)+","+str(SolarPower)+","+str(HomePower)+","+str(HomeVoltage)+","+str(BatteryPower)+","+str(HomePower)+","+str(BatteryCharge)+","+str(GirdPower)+","+str(HomeFrequency)+","+str(SolarPower))
            pvocon=Connection(pvo_key, pvo_sysid, pvo_host)
            pvocon.add_status(pvoDate, pvoTime, power_exp=SolarPower, power_imp=HomePower, voltage=HomeVoltage, battery=BatteryPower, home=HomePower, soc=BatteryCharge, gird=GirdPower, frequency=HomeFrequency, solar=SolarPower)
        else:
            print(str(pvoDate)+","+str(pvoTime)+", Error: No data to sent")
            logger.info(str(pvoDate)+","+str(pvoTime)+", Error: No data to sent")
    except StandardError as e:
        logger.info(str(e))
        time.sleep(30)
1 Like

no, i didn’t put any carets or anything… it just didn’t work. my syntax is exactly as you have quoted. i even logged in once more and got a new token and then immediately tried it.

1 Like

thanks, as it turns out i was using PowerWall2PVOutput and started looking into how to have it handle the login and cookie and pretty quickly realized that it was based on some pretty old stuff (urllib instead of request) and will take more python knowledge than i have to fix. i’ll give your code a try.

Try sending back just the AuthCookie returned from gateway login, no token.

curl -k --cookies "AuthCookie=<cookie_data>" https://192.168.xxx.xxx/api/meters/aggregates

Please test the following patch which will now login to the gateway -

  1. Stop the service
  2. Make a backup of file <pvoutput_install>\lib\org.pvoutput.integration.jar
  3. Download the patch -
  4. Rename from org.pvoutput.integration_1.5.5.1.jar to org.pvoutput.integration.jar
  5. Copy org.pvoutput.integration.jar to the PVOutput installation lib folder, replacing the existing file.
  6. Edit conf\powerwall.ini and add lines with gateway ip
    • login-url=https://192.168.x.x/api/login/Basic
    • login-pass=your_password
  7. Start the service

If the above works v1.5.5.1 will be released.

2 Likes

sorry - i had gone to bed (PST) but i did try this just now and i got data back from the powerwall. so passing the auth cookie does work.

i’ll try the java program but it might take me a little while as i’ve been using the python scripts up to this point.

@bankstownbloke - it works, thank you!


 2021-02-10 09:13:09,382  INFO [Thread-2] (WebClient.java:226) - >>> https://192.168.0.136/api/login/Basic
2021-02-10 09:13:09,397  INFO [Thread-1] (Controller.java:435) - Found 1 Sensors
2021-02-10 09:13:09,397  INFO [Thread-1] (Controller.java:536) - Added Reader: powerwall0
2021-02-10 09:13:09,397  INFO [Thread-1] (ADataLogReader.java:350) - Output stop at 1080 minutes
2021-02-10 09:13:09,397  INFO [Thread-1] (Controller.java:560) - Log File: powerwall0 [PW0-2021-02-10.log]
2021-02-10 09:13:09,397  INFO [Thread-1] (Controller.java:572) - Export Sensor: 0, id: 0
2021-02-10 09:13:09,413  INFO [Thread-1] (Controller.java:579) - Service: [http://pvoutput.org:80/service/r2/addbatchstatus.jsp] Test: false, End: 18:00
2021-02-10 09:13:09,413  INFO [Thread-1] (Controller.java:587) - Loaded 1 Readers (Import: 0, Export: 1)
2021-02-10 09:13:10,647  INFO [Thread-1] (Controller.java:1524) - Records restored from status.log : 25932
2021-02-10 09:13:11,709  INFO [Thread-2] (PowerwallLogReader.java:72) - Successful gateway authentication
2021-02-10 09:13:11,709  INFO [Thread-2] (WebClient.java:356) - >>> https://192.168.0.136:443/api/meters/aggregates
2021-02-10 09:13:11,834  INFO [Thread-2] (WebClient.java:157) - >>> https://192.168.0.136/api/system_status/soe
2021-02-10 09:13:12,647  INFO [Thread-1] (Controller.java:731) - Startup Complete: Waiting for data...
2021-02-10 09:13:12,678  INFO [Thread-1] (Controller.java:1806) - >>> 20210210,09:15,-1.0,3536,-1,-1,-1000.0,-1.0,10,483.026,60,-3065.93,99.043,3536.38
2021-02-10 09:13:12,678  INFO [Thread-1] (WebClient.java:135) - >>> http://pvoutput.org:80/service/r2/addbatchstatus.jsp?data=20210210,09:15,-1.0,3536,-1,-1,-1000.0,-1.0,10,483.026,60,-3065.93,99.043,3536.38
2021-02-10 09:13:12,804  INFO [Thread-1] (Controller.java:1834) - <<< 20210210,09:15,1
2 Likes

Thanks for confirming this.

PVOutput Integration Service v1.5.5.1 released with the Powerwall authentication requirement for firmware version 20.49.0

5 Likes

I have just reinstalled using your updated PVOutput Integration Service v1.5.5.1 and everything is up and running again - many thanks for addressing this issue so promptly.

1 Like

Good work as always!
I installed everything from scratch using the PVOutput_Integration_Service_v1.5.5.1_Setup
and eventually got everything to work. However, it seems like the wrapper is a 32bit version while I only have JVM 64bit installed.
What do you recommend ?
Here is the error:
STATUS | wrapper | 2021/02/17 20:55:07 | --> Wrapper Started as Service
STATUS | wrapper | 2021/02/17 20:55:07 | Java Service Wrapper Community Edition 32-bit 3.5.4
STATUS | wrapper | 2021/02/17 20:55:07 | Copyright © 1999-2010 Tanuki Software, Ltd. All Rights Reserved.
STATUS | wrapper | 2021/02/17 20:55:07 | http://wrapper.tanukisoftware.com
STATUS | wrapper | 2021/02/17 20:55:07 |
STATUS | wrapper | 2021/02/17 20:55:08 | Launching a JVM…
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: Initializing…
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager:
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: WARNING - Unable to load the Wrapper’s native library ‘wrapper.dll’.
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: The file is located on the path at the following location but
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: could not be loaded:
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: C:\Program Files (x86)\PVOutput\bin…\lib\wrapper.dll
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: Please verify that the file is both readable and executable by the
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: current user and that the file has not been corrupted in any way.
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: One common cause of this problem is running a 32-bit version
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: of the Wrapper with a 64-bit version of Java, or vica versa.
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: This is a 64-bit JVM.
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: Reported cause:
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: C:\Program Files (x86)\PVOutput\lib\wrapper.dll: Can’t load IA 32-bit .dll on a AMD 64-bit platform
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager: System signals will not be handled correctly.
INFO | jvm 1 | 2021/02/17 20:55:08 | WrapperManager:
INFO | jvm 1 | 2021/02/17 20:55:08 | *** Starting PVOutput Integration Service v1.5.5.1
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.runtime.name=Java™ SE Runtime Environment
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.version=25.281-b09
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.vendor=Oracle Corporation
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vendor.url=http://java.oracle.com/
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.name=Java HotSpot™ 64-Bit Server VM
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.specification.name=Java Virtual Machine Specification
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.runtime.version=1.8.0_281-b09
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.endorsed.dirs=C:\Program Files\Java\jre1.8.0_281\lib\endorsed
INFO | jvm 1 | 2021/02/17 20:55:08 | >> os.arch=amd64
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.io.tmpdir=C:\WINDOWS\system32\config\systemprofile\AppData\Local\Temp
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.specification.vendor=Oracle Corporation
INFO | jvm 1 | 2021/02/17 20:55:08 | >> os.name=Windows 10
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.library.path=…/lib
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.specification.name=Java Platform API Specification
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.class.version=52.0
INFO | jvm 1 | 2021/02/17 20:55:08 | >> os.version=10.0
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.awt.printerjob=sun.awt.windows.WPrinterJob
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.specification.version=1.8
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.class.path=…/lib/wrapper.jar;…/lib/org.pvoutput.integration.jar;…/lib/commons-logging-1.1.1.jar;…/lib/httpcore-4.1.2.jar;…/lib/httpclient-4.1.2.jar;…/lib/jetty-http-7.5.1.v20110908.jar;…/lib/jetty-util-7.5.1.v20110908.jar;…/lib/jetty-io-7.5.1.v20110908.jar;…/lib/jetty-server-7.5.1.v20110908.jar;…/lib/jetty-continuation-7.5.1.v20110908.jar;…/lib/servlet-api-2.5.jar;…/lib/json_simple-1.1.jar;…/lib/jxl.jar;…/lib/log4j-1.2.15.jar;…/lib/RXTXcomm.jar;…/lib/jackcess-1.2.2.jar;…/lib/bsh-core-2.0b4.jar;…/lib/sqlitejdbc-v056.jar;…/lib/commons-net-3.1.jar
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.specification.version=1.8
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.home=C:\Program Files\Java\jre1.8.0_281
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.specification.vendor=Oracle Corporation
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vm.info=mixed mode
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.version=1.8.0_281
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.ext.dirs=C:\Program Files\Java\jre1.8.0_281\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vendor=Oracle Corporation
INFO | jvm 1 | 2021/02/17 20:55:08 | >> java.vendor.url.bug=http://bugreport.sun.com/bugreport/

Could I suggest that this step is included in the “Upgrading.html” file in the update package? For my PW the default password is the last 5 digits of the serial number https://www.tesla.com/en_gb/support/energy/powerwall/own/monitoring-from-home-network .

Thanks for the install note, John.
I have added the lines to conf\powerwall.ini as per image:

however, getting this error:

NFO [Thread-2] (WebClient.java:226) - >>> https://192.168.1.zzz![19-002|602x500] /api/login/basic
2021-02-19 14:21:46,949 WARN [Thread-2] (DefaultRequestDirector.java:1095) - Authentication error: Unable to respond to any of these challenges: {}
2021-02-19 14:21:46,949 ERROR [Thread-2] (WebClient.java:298) - <<< [401] {“code”:401,“error”:“Provider does not exist basic”,“message”:“Login Error”}
2021-02-19 14:21:46,949 WARN [Thread-2] (PowerwallLogReader.java:77) - Failed gateway authentication

Is that first letter of “basic” case-sensitive? I used the capital letter as in the instructions.

You can check if the password OK by doing a manual login to the gateway’s IP address. It now wants an email address and password in order to show the animate power flow display.

1 Like

Brilliant John!
That was exactly it (Basic with a capital B).
All good now Thank you to you, bankstownbloke and rpfile for getting this working again.
Very happy!

Cheers

This is only a warning, the service should start and pvoutput.log will show activity.

1 Like