SonnenladenGmbH / APsystems-EZ1-API

The APsystems EZ1 Python library offers a streamlined interface for interacting with the local API of APsystems EZ1 Microinverters.
MIT License
60 stars 13 forks source link

[Bug]: TypeError: unsupported operand type(s) for |: 'type' and 'NoneType' #22

Closed TLINDEN closed 5 months ago

TLINDEN commented 5 months ago

What happened?

When trying to execute the supplied sample script, I get a python error.

The python error

python basic.py 
Traceback (most recent call last):
  File "/home/scip/APsystems-EZ1-API/basic.py", line 1, in <module>
    from APsystemsEZ1 import APsystemsEZ1M # import the APsystemsEZ1 library
  File "/home/scip/APsystems-EZ1-API/APsystemsEZ1/__init__.py", line 45, in <module>
    class APsystemsEZ1M:
  File "/home/scip/APsystems-EZ1-API/APsystemsEZ1/__init__.py", line 56, in APsystemsEZ1M
    session: ClientSession | None = None
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'


### Your python version

3.9.2

### Your OS inlcuding your version

Raspbian GNU/Linux 11
TLINDEN commented 5 months ago

I'm trying to use it on an old Raspberry Pi B+. I could not install the module using pip:

pip install apsystems-ez1
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
ERROR: Could not find a version that satisfies the requirement apsystems-ez1
ERROR: No matching distribution found for apsystems-ez1

Unfortunately you don't provide a setup.py so I can't build and install it directly. Therefore I just cloned the git repo and work from there.

mawoka-myblock commented 5 months ago

You need a more recent python version. 3.11 or at least 3.10

TLINDEN commented 5 months ago

Well, there's no python 3.11 package available for this system. And it's way too slow to compile it manually. So, I'll use good old curl and stick with it.

However, you should think about being backwards compatible. We're in the IOT world here, there are sometimes devices where you can't have the latest and shiniest releases.

TLINDEN commented 5 months ago

Ok, just for the record in case someone else stumbles upon this. Here's how I solved it w/o the python script:

I created this shellscript:

#!/bin/bash
host="192.168.128.117:8050"
metrics="getOutputData"
info="getDeviceInfo"
ts=$(date +%Y-%m-%dT%H:%M:%S+01:00)

data=$(curl -s http://$host/$metrics | jq -r '.data | join (" ")')

if test -n "$data"; then
 read -r -a params <<< "${data}"
 p1="${params[0]}"   # power generating on channel 1
 e1="${params[1]}"   # energy generated since startup on channel 1
 te1="${params[2]}"  # lifetime energy generated on channel 1
 p2="${params[3]}"
 e2="${params[4]}"
 te2="${params[5]}"
else
    echo "$ts ot no data!"
    return
fi

infodata=$(curl -s http://$host/$info | jq -r '.data | join (" ")')

if test -n "$infodata"; then
 read -r -a params <<< "${infodata}"
 deviceid="${params[0]}"
 device="${params[1]}"
 version="${params[2]}"
 ssid="${params[3]}" 
 ip="${params[4]}"
 minpower="${params[5]}"
 maxpower="${params[6]}"
else
    echo "$ts ot no info!"
    return
fi

if test -n "$p1" -a -n "$ip"; then
    echo "ts=$ts p1=$p1 p2=$p2 ip=$ip version=$version deviceid=$deviceid ssid=$ssid minpower=$minpower maxpower=$maxpower" | ssh cloud "cat >> var/log/solar.metric"
else
    echo "$ts got invalid data!"
fi

This runs as a cronjob on my Raspi and uploads the result to a machine I have running in the cloud. There I use Promtail to scrape this file and put it into Loki. This is the result in grafana:

tomsolar

The graphs are pretty simple. The first one uses these two queries:

# 1:
max_over_time({filename="/home/user/var/log/solar.metric"} |= `p1` | logfmt | unwrap p1 | __error__="" [5m]) by (instance)

# 2:
max_over_time({filename="/home/user/var/log/solar.metric"} |= `p2` | logfmt | unwrap p2 | __error__="" [5m]) by (instance)

and uses a Transform to add the two metrics so that I get a summary graph.

The other graph just shows the same metrics separately. And the table extracts the info fields using this query:

{filename="/home/user/var/log/solar.metric"} | logfmt

and uses 3 transforms to create the info view:

1) Extract fields: labels => JSON 2) Organize fields: don't display timeseries value and only the fields we need, also rename them properly 3) Reduce: series to rows, Calculations: last

best, Tom