App to set the Powerwall's standby reserve programmatically. Saves me having
to wake up at 00:30 and 04:30 to tweak it via the app.

See here for some basic info on the Tesla API:

	https://www.teslaapi.io
and
	https://www.teslaapi.io/energy-sites/state-and-settings

Use a 3rd party website to generate the access/refresh tokens. This will
also need doing if the Tesla ID password is changed, or if Tesla themselves
revoke the tokens. Note that the access token self-expires after 8 hours.

	https://tesla-info.com/tesla-token.php

Paste the refresh token into a new file called "sso_refresh_token.txt".
In 'headerfile', replace ACCESS_TOKEN with the access token generated.

Fetch details of your Tesla products:
	curl -H @headerfile "https://owner-api.teslamotors.com/api/1/products" | json_pp

Note, you don't need to use json_pp to format the JSON, but it'll make life
a whole lot easier.

The JSON will contain an array whose entries correspond to each Tesla
product you own. Search for "energy_site_id" to locate the Powerwall
entry. Paste the value of this field into the "site_id" field of
the pwstandby.json file.

Now look for the "id" field in the Powerwall JSON. Paste the value of
this field into the "pw_id" field of the pwstandby.json file.

Other tweakable values in /usr/local/etc/tesla_api/pwstandby.json:

	- Set "enabled" to true or false. The latter will prevent the
	  Python script from modifying the Powerwall standby reserve.
	- Set the Powerwall standby reserve values.

Copy pwstandby.py to /usr/local/sbin/pwstandby.py
Populate /usr/local/etc/tesla_api with a minimum of:

	pwstandby.json
	sso_refresh_token.txt

Add a cron entry for root using "crontab -u root -e". Populate with:

	#minute hour    mday    month   wday    command

	# Set the standby reserve to force Powerwall to charge from off-peak
	31      0       *       *       *       /usr/local/sbin/pwstandby.py on

	# Restore standby reserve.
	25      4       *       *       *       /usr/local/sbin/pwstandby.py off


For experimenting...

Insert the access token into 'headerfile' in this directory. Note: You may
be able to grab /usr/local/etc/tesla_api/access_token.txt rather then
generate a new one. Be aware that it may have expired.

With the access token in 'headerfile', we can use 'curl' to query some stuff:

Ok, subset of data returned using:
	curl -H @headerfile "https://owner-api.teslamotors.com/api/1/products" | json_pp

<quote>
         "percentage_charged" : 67.3922895643241,
         "components" : {
            "load_meter" : true,
            "solar" : true,
            "battery_type" : "ac_powerwall",
            "grid" : true,
            "market_type" : "residential",
            "battery" : true,
            "solar_type" : "pv_panel"
         },
         "resource_type" : "battery",
         "total_pack_energy" : 13936,
         "site_name" : "Angry Pixie Harvesting Device",
         "energy_left" : 9391.78947368421,
         "sync_grid_alert_enabled" : true,
         "energy_site_id" : 123456789ABC,
         "asset_site_id" : "????????-????-????-????-????????????",
         "breaker_alert_enabled" : false,
         "battery_power" : -2740,
         "backup_capable" : true,
         "battery_type" : "ac_powerwall",
         "id" : "STE12345678-ABCDE",
         "gateway_id" : "???????-??-?--??????????????"
</quote>

In the above JSON, "energy_site_id" is passed to URLs with /api/1/energy_sites/...
while "id" is passed to URLs with /api/1/powerwalls/...

Use this to get the status of the individual Powerwall:
	curl -H @headerfile https://owner-api.teslamotors.com/api/1/powerwalls/STE12345678-ABCDE/status|json_pp

	<quote>
	{
		"response" : {
			"total_pack_energy" : 13936,
			"site_name" : "Angry Pixie Harvesting Device",
			"energy_left" : 11199.1578947368,
			"battery_power" : 260,
			"id" : "???????-??-?--??????????????",
			"percentage_charged" : 80.3613511390416
		}
	}
	</quote>

Use this to get the status of the energy site:
	curl -H @headerfile https://owner-api.teslamotors.com/api/1/energy_sites/123456789ABC/site_status|json_pp

	<quote>
	{
	   "response" : {
	      "battery_power" : -3120,
	      "percentage_charged" : 78.5712127621004,
	      "site_name" : "Angry Pixie Harvesting Device",
	      "energy_left" : 10949.6842105263,
	      "gateway_id" : "???????-??-?--??????????????",
	      "total_pack_energy" : 13936,
	      "backup_capable" : true,
	      "resource_type" : "battery",
	      "sync_grid_alert_enabled" : true,
	      "breaker_alert_enabled" : false,
	      "battery_type" : "ac_powerwall"
	   }
	}
	</quote>

Another interesting url:
	curl -H @headerfile https://owner-api.teslamotors.com/api/1/energy_sites/123456789ABC/site_info | json_pp

	<quote>
	{
           "response" : {
              "min_site_meter_power_ac" : -1000000000,
              "components" : {
                 "storm_mode_capable" : true,
                 "battery_type" : "ac_powerwall",
                 "grid_services_enabled" : false,
                 "battery" : true,
                 "wifi_commissioning_enabled" : true,
                 "backup_time_remaining_enabled" : true,
                 "grid" : true,
                 "configurable" : true,
                 "energy_value_header" : "Energy Value",
                 "energy_value_subheader" : "Estimated Value",
                 "battery_solar_offset_view_enabled" : true,
                 "solar" : true,
                 "gateway" : "teg",
                 "vehicle_charging_solar_offset_view_enabled" : false,
                 "tou_capable" : true,
                 "car_charging_data_supported" : false,
                 "vehicle_charging_performance_view_enabled" : false,
                 "solar_type" : "pv_panel",
                 "set_islanding_mode_enabled" : true,
                 "load_meter" : true,
                 "solar_value_enabled" : true,
                 "backup" : true,
                 "off_grid_vehicle_charging_reserve_supported" : false,
                 "flex_energy_request_capable" : false,
                 "show_grid_import_battery_source_cards" : true
              },
              "backup_reserve_percent" : 15,
              "nameplate_energy" : 13500,
              "max_site_meter_power_ac" : 1000000000,
              "installation_date" : "2021-10-06T16:40:58+01:00",
              "version" : "22.9.1 bce98cad",
              "default_real_mode" : "autonomous",
              "installation_time_zone" : "Europe/London",
              "user_settings" : {
                 "sync_grid_alert_enabled" : true,
                 "storm_mode_enabled" : false,
                 "breaker_alert_enabled" : false
              },
              "battery_count" : 1,
              "nameplate_power" : 5000,
              "id" : "???????-??-?--??????????????",
              "site_name" : "Angry Pixie Harvesting Device",
              "tou_settings" : {
                 "optimization_strategy" : "economics",
                 "schedule" : [
                    {
                       "end_seconds" : 16200,
                       "target" : "off_peak",
                       "week_days" : [
                          1,
                          0
                       ],
                       "start_seconds" : 1800
                    },
                    {
                       "end_seconds" : 1800,
                       "start_seconds" : 16200,
                       "week_days" : [
                          1,
                          0
                       ],
                       "target" : "peak"
                    }
                 ]
              }
           }
        }
	</quote>
