dannerph / homeassistant-solcast

Apache License 2.0
19 stars 3 forks source link

Blueprint to push updates/history #6

Closed elRadix closed 3 years ago

elRadix commented 3 years ago

Can you please create a blueprint automation to facilite the way to push updates/history as the current instructions is really not clear at least for me. This would help also a lot of new users.

Thank your for thinking about it.

B-Hartley commented 3 years ago

I did it like this, probably overly complex, but it worked.

automation:
  - id: solcast_push_measurement
    alias: "Solcast Push Measurement"
    trigger:
      platform: time_pattern
      minutes: "/30"
    action:
      - choose:
            # Average Power less than 10kWh and Last Meter Was stored between 29 and 31 mins  
          - conditions: >
              {{ ((states('sensor.solaredge_lifetime_production') | float -  states('input_number.solar_meter_30_mins_ago') | float) * 12.0 < 10.0) and
              ((as_timestamp(now())-state_attr('input_datetime.solar_meter_last_stored_data', 'timestamp')) < 1860)  and
              ((as_timestamp(now())-state_attr('input_datetime.solar_meter_last_stored_data', 'timestamp')) > 1740)   }}
            sequence:
              - service: solcast.push_measurement
                data:
                  total_power: "{{ (((states('sensor.solaredge_lifetime_production') | float) -  (states('input_number.solar_meter_30_mins_ago') | float)) * 2.0) | round(2) }}"        
                  period: 'PT30M'
                  period_end: "{{ utcnow() |  replace(' ','T') }}"    
              - service: input_number.set_value
                data:
                  entity_id: input_number.solar_meter_30_mins_ago
                  value: "{{ states('sensor.solaredge_lifetime_production') }}"
              - service: input_datetime.set_datetime
                data:
                  entity_id: input_datetime.solar_meter_last_stored_data
                  datetime: "{{ now() }}"
        default:
          - service: input_number.set_value
            data:
              entity_id: input_number.solar_meter_30_mins_ago
              value: "{{ states('sensor.solaredge_lifetime_production') }}"        
          - service: input_datetime.set_datetime
            data:
              entity_id: input_datetime.solar_meter_last_stored_data
              datetime: "{{ now() }}"

I've now switched to doing an overnight batch outside of home assistant. I download the day from Solaredge, reformat it and upload it to Solcat.

dannerph commented 3 years ago

I initially thought of having some automatic measurement push to solcast, however the data source of different users is different too.

I like the idea of @B-Hartley to use the metering value. However, I have a question on the purpose of the condition: Could you explain it to me?

It should be possible to integrate the logic of your automation into the components itself, so that you only need to specify the sensor, that holds the energy meter data. I guess with the contidions you check the plausibility of the values, correct?

B-Hartley commented 3 years ago

Yes. The conditions just check that everything is ok with the data. If a restart or similar prevented the previous reading being taken then it won’t upload the data.

B-Hartley commented 3 years ago

I upload now in batch using a script like this........


import requests
import re
import json
import datetime

yesterday_date =  str(datetime.date.today()+datetime.timedelta(days=-1))
url = 'https://monitoringapi.solaredge.com/site/xxxxxxx/energy?timeUnit=QUARTER_OF_AN_HOUR&endDate=' + yesterday_date + '&startDate=' + yesterday_date + '&api_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
req = requests.get(url)

#json_file = './input.txt'
#json_filehandle=open(json_file,'r')
#json_object=json.load(json_file)
json_object = json.loads(req.text)
jsonObj = {"measurements": []}

dict = json_object['energy']['values']
for dateValue in dict:
    date_time_str = dateValue["date"]
    dateValue_value = dateValue["value"]
    if dateValue_value == None:
      dateValue_value = 0.0
    date_time_obj = datetime.datetime.strptime(date_time_str,'%Y-%m-%d %H:%M:%S')
    date_time_fifteen = date_time_obj + datetime.timedelta(minutes=15)
    periodDetails = {
        "period_end": date_time_fifteen.strftime('%Y-%m-%dT%H:%M:%S.000000+00:00'),
        "period": "PT15M",
        "total_power": round(dateValue_value*4.0/1000.0,3)
    }
    jsonObj["measurements"].append(periodDetails)

post_url='https://api.solcast.com.au/rooftop_sites/xxxx-xxxxxxxx-xxxx/measurements'
headers = {'Authorization': 'Bearer xxxxxxxxxxxxxxxxxxxxxxx'}
result=requests.post(post_url,json=jsonObj, headers=headers)
elRadix commented 3 years ago

@B-Hartley I also have a solaredge system, how do you launch your python script from hassio? Which interval?

B-Hartley commented 3 years ago

I run it on a separate pi on a cron job. if someone could convert it to run within home assistant that would be great. maybe app daemon. Or perhaps just native. I don’t really know. It runs early hours each day.

elRadix commented 3 years ago

@B-Hartley, So to get the python script working I need to update the solaredge api and solcast site and api

I still don't see the measurements on the solcast overview.

B-Hartley commented 3 years ago

Yes. You need to get and fill in the site ids and api keys for solaredge and solcast. then run the script.

I have a version that has some debug print statements in it so you can see what it’s doing. Or you could add some.

elRadix commented 3 years ago

If you could share the Debug version would be great as I'm not python developer. Thank you

B-Hartley commented 3 years ago
import requests
import re
import json
import datetime

yesterday_date =  str(datetime.date.today()+datetime.timedelta(days=-1))
url = 'https://monitoringapi.solaredge.com/site/xxxxxxx/energy?timeUnit=QUARTER_OF_AN_HOUR&endDate=' + yesterday_date + '&startDate=' + yesterday_date + '&api_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
req = requests.get(url)

#json_file = './input.txt'
#json_filehandle=open(json_file,'r')
#json_object=json.load(json_file)
json_object = json.loads(req.text)
jsonObj = {"measurements": []}

dict = json_object['energy']['values']
for dateValue in dict:
    date_time_str = dateValue["date"]
    dateValue_value = dateValue["value"]
    if dateValue_value == None:
      dateValue_value = 0.0
    date_time_obj = datetime.datetime.strptime(date_time_str,'%Y-%m-%d %H:%M:%S')
    date_time_fifteen = date_time_obj + datetime.timedelta(minutes=15)
    periodDetails = {
        "period_end": date_time_fifteen.strftime('%Y-%m-%dT%H:%M:%S.000000+00:00'),
        "period": "PT15M",
        "total_power": round(dateValue_value*4.0/1000.0,3)
    }
    jsonObj["measurements"].append(periodDetails)

print('info to send to  SolCast')
print('------------------------')
print(json.dumps(jsonObj))

post_json = json.dumps(jsonObj)

post_url='https://api.solcast.com.au/rooftop_sites/xxxx-xxxx-xxxx-xxxx/measurements'
headers = {'Authorization': 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
result=requests.post(post_url,json=jsonObj, headers=headers)
print('-----------------------')
print('response from Solcast')
print('-----------------------')
print('{"result":' + str(result.status_code) + ', "date":"' + date_time_fifteen.strftime('%Y-%m-%dT%H:%M:%S') + '"}')
print(result.text)
dannerph commented 3 years ago

obsolete with #12 ?