Package: openpower
openpowerPython library for monitoring and controlling solar panels, inverters, batteries and power retailers.  an AlphaESS battery/inverter using the AlphaCloud opne APISupported SystemsRetailersAmber (Australia)BatteriesAlphaESS (using the Open API)InvertersAlphaESS (using the Open API)Goodwe (using the Open API) -in developmentAlphaESSHow to use1. Sign up for an open API accountRegister athttps://open.alphaess.com/for a (free) account to get your Developer ID (AppID) and Developer Secret (AppSecret).Once registered, add your battery/inverter to the developer account via the web UI. (Adding a battery/inverter can also be automated using theget_verification_code()andbind_system()methods)2. Get startedfrom openpower.alphaess import AlphaESS

APP_ID = "the AppID from step 1"
APP_SECRET = "the AppSecret from step 1"

api = AlphaESS(app_id=APP_ID, app_secret=APP_SECRET)

devices = api.list_systems()
print(devices)

for device in devices:
	print("Currently consuming/feeding in:", api.for_device(device["sysSn"]).get_realtime_power_usage()["pgrid"])MethodsConstructor:AlphaESS(app_id: str, app_secret: str, device_serial_number: str = None)Parameters:app_id: (str) (required) The app ID of your developer accountapp_secret: (str) (required) The app secret of your developer accountdevice_serial_number: (str) (optional) If specified, this will be used as the default serial number for methods related to a specific device, if none is specified in the method.Devicesfor_device(serial_number: str)A convenience wrapper that clones the current instance and sets the serial number so that further calls do not need the serial number passed in. Every device-specified method can have the serial number provided in the method, in the class constructor or using this method.Parameters:serial_number: The serial number of the device to scope future requests to, available fromlist_systems()Returns:A new instance ofAlphaESSwith the serial number setlist_systems()Lists the available systems to monitor/control. Additional systems can be added via the web UI or by callingget_verification_code()andbind_system(). Systems can also be removed withunbind_system().Returns:A list of systems, uncluding serial number (sysSn) and model, that are whitelisted for this developer accountget_verification_code(check_code: str)This is the first step to "binding" (adding) a new system to the developer account to allow it to be monitored and controlled. It will send an enamil to the registered owner of the system with a verification code that can be used onbind_system()Parameters:check_code: (str) (required) The check code shown on the battery/inverter's physical label below the serial numberserial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:Nothing.Note that this method will email the battery/inverter's owner with a code, so check the details thoroughly.bind_system(verification_code: str)Binds (adds) a battery/inverter to the developer's account to allow it to be monitored and controlled. This can only be done after callingget_verification_code()(or via the web UI).Parameters:verification_code: (str) (required) The code which was sent via email to the registered owner when callingget_verification_code(). This isnotthe check code.serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:Nothing. The system will now be visible when you calllist_systems()unbind_system()Unbind (remove) a battery/inverter from the developer account.Parameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:
Nothing.Power Monitoringget_realtime_energy_usage()Gets the current power usage, typically in 30 second blocks.Parameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:A dictionary of real-time data from the battery:FieldDescriptionIn-App EquivalentUnitppvPV PowerSolar PowerWploadPower LoadLoadWsocBattery charge levelState of Charge% [0...1]pgridGrid Consumption (if negative, this is the feed-in value)Grid Consumption / Feed-InWpbatPower from battery (if negative, battery is charging)BatteryWpevTotal power of charging pile?Wget_system_summary()Gets an overall summary of the system, including total power, CO2 savings, trees planted and profit/payback.Parameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:A dictionary of fields (todo: document these in detail). All electricity values are in kWh, all % are [0...1], CO2 is in kg andtodayIncomeandtotalIncomeis in the currency specified bymoneyType.get_historical_power_usage(date: date)Gets the power usage for a specific dayParameters:date(datetime.date) The date to get data forserial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodget_historical_energy_usage(date: date)Gets the energy usage for a specific day (todo: document the difference between power and energy - this is evident in the returned fields)Parameters:date(datetime.date) The date to get data forserial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodSystem Configurationget_charging_settings()Gets the charging settingsParameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:FieldDescriptionbatHighCap% to stop charging from grid at [0...1]gridChargeWhether to charge from the grid (0 or 1)timeChaf1Start time of charging period 1 (HH:mm, 24 hour time, must be a 15 min interval)timeChae1End time of charging period 1 (HH:mm, 24 hour time, must be a 15 min interval)timeChaf2Start time of charging period 2 (HH:mm, 24 hour time, must be a 15 min interval)timeChae2End time of charging period 2 (HH:mm, 24 hour time, must be a 15 min interval)set_charging_settings(stop_level: float, use_grid: bool, first_period: tuple[datetime.time, datetime.time], second_period: tuple[datetime.time, datetime.time])Parameters:stop_level(float) % to stop charging from the grid at [0...1]use_grid(bool) True to charge from the grid, False not tofirst_period(tuple ofdatetime.time) The start and end time of charging period 1 (the minutes for both fields must be one of :00, :15, :30, :45)second_period(tuple ofdatetime.time) The start and end time of charging period 2 (the minutes for both fields must be one of :00, :15, :30, :45)serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodget_discharging_settings()Gets the discharging settingsParameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:FieldDescriptionbatUseCap% to stop discharging at [0...1]ctrDisWhether to enable time-based discharge control (0 or 1)timeDisf1Start time of discharging period 1 (HH:mm, 24 hour time, must be a 15 min interval)timeDise1End time of charging period 1 (HH:mm, 24 hour time, must be a 15 min interval)timeDisf2Start time of discharging period 2 (HH:mm, 24 hour time, must be a 15 min interval)timeDise2End time of discharging period 2 (HH:mm, 24 hour time, must be a 15 min interval)set_discharging_settings(stop_level: float, enable_time_control: bool, first_period: tuple[datetime.time, datetime.time], second_period: tuple[datetime.time, datetime.time])Parameters:stop_level(float) % to stop discharging at [0...1]enable_time_control(bool) True to use time-based discharging control, Flase not tofirst_period(tuple ofdatetime.time) The start and end time of discharging period 1 (the minutes for both fields must be one of :00, :15, :30, :45)second_period(tuple ofdatetime.time) The start and end time of discharging period 2 (the minutes for both fields must be one of :00, :15, :30, :45)serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodEV Chargersget_ev_charger_list()Get a list of the the EV chargers in the battery system.Parameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:A list of the EV chargers model and serial number.get_ev_charger_current_draw_settings()Get the total maximum EV current draw allowed.Parameters:serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:The maximum current, in Amps, as a floatset_ev_charger_current_draw_settings(current_draw: float)Set the maximum EV current draw tocurrent_drawParameters:current_draw(float) The maximum current draw, in Amps, as a floatserial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodReturns:Nothing if succesful. As with all requests, an exception will be raised if an error occurs.get_ev_charger_status(charger_serial_number: str)Get the status of an EV chargerParameters:charger_serial_number(str) The serial number to retrieve status for, seeget_ev_charger_list()serial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodcontrol_ev_charger(charger_serial_number: str, charging: bool)Enable or disable an EV chargerParameters:charger_serial_number(str) The serial number to retrieve status for, seeget_ev_charger_list()charging(bool) True to enable the charger, False to disable chargingserial_number(str) (optional) The serial number of the battery/inverter. This can alternatively be passed in via the constructor or by using thefor_device()helper methodAmberThis is a direct implementation ofAmber's developer API.How to use1. Get a developer tokenYou must be an Amber customer to get a developer token.Login to the customer portal via the web UIIn Settings, enable Developer Mode and refresh the pageIn For Developers (which appears after step #2), generate an API token2. Get startedfrom openapi.amber import Amber

api = Amber(token="your API token from step 1")

sites = api.list_sites()

for site in sites:
    print("Current prices are:", api.for_site(site["id"]).get_current_prices(previous=0, next=0))MethodsConstructor:Amber(token: str, site: Optional[str] = None)Parameters:token(str) The API token to use (from the developer portal)site(str) (optional) If specified, the default site ID to use if none is specified in the method and thefor_site()helper method is not utilsied.API Helper Methodsfor_site(site: str)A convenience wrapper that clones the current instance and sets the site ID so that further calls do not need the site ID passed in. Every site-specified method can have the site ID provided in the method, in the class constructor or using this method.Parameters:site: The site ID to scope future requests to, available fromlist_sites()Returns:A new instance ofAmberwith the site ID setget_ratelimits()If a previous API call has been made (excludingget_current_renewables()), this will provide the latest rate limit information to assist in throttling additional requests. Currently, Amber allows 50 requests per 5 minutes.Parameters:None.Returns:If an API request has been made previously, this returns an object with:limitThe maximum allowed requests in the time windowremainingThe remaining requests allowed in the time windowresetThe number of seconds until the count will be resetpolicyThe ratelimiting policy in effectrefreshed(datetime.datetime) The time the rate limits were last retrieved (i.e. the tiem of the last API call)In addition, there are two helper methods:get_estimated_reset()which returns adatetime.datetimeof when the rate limit will reset. This could be in the past ifrefreshedis not recent.get_time_window()which returns the current time window used for rate limiting. This is done by crudely parsing thepolicyand could break if a more complex policy was implemented.If there is no rate limit information yet, returnsNoneCurrent Renewablesget_current_renewables(state: State, previous: Optional[int], next: Optional[int], resolution: Optional[int])Gets the current % of renewables in the grid for a specific state. This request is not rate-limited and does not return rate-limit information so does not affectget_ratelimits()Parameters:state(State) The state to get data for - seelist(State)to get a list of allowed Statesprevious(int) (optional) The number of prior data points to retrievenext(int) (optional) The number of future predictions to retrieveresolution(int) (optional) The time resolution (in minutes) to retrieve. Currently only supports 30Returns:Information about the percentage of renewables in the gridExample:from openpower.amber import Amber, State


AMBER_TOKEN = "Your token here"

amber = Amber(AMBER_TOKEN)

print("Available states:", list(State))
print("Current renewables:", amber.get_current_renewables(State.VICTORIA, previous=0, next=0))Site-Specific Datalist_sites()Gets a list of available sites linked to the current API tokenParameters:NoneReturns:A list of sites with ID, NMI, status and network. The ID is used as the site ID in other methods. At current, it appears customers can have only one active site, but may have multiple sites if they've moved address, so it is best to filter the results bystatus=active.get_current_prices(previous: Optional[int], next: Optional[int], resolution: Optional[int], site: Optional[str])Get the current price of electricity on all channels. The results are supposed to be ordered by General, Controlled Load then Feed In (solar) however there have been times when this wasn't being done by Amber's API servers, so it is recommended to filter by channelParameters:previous(int) (optional) The number of prior data points to retrievenext(int) (optional) The number of future predictions to retrieveresolution(int) (optional) The time resolution (in minutes) to retrieve. Currently only supports 30Returns:A list of channels and pricesget_prices(start: Optional[date], end: Optional[date], resolution: int)Get historical price data for a siteParameters:start(datetime.date) (optional) The first day to retrieve data for (inclusive), defaults to todayend(datetime.date) (optional) The last day to retrieve data for (inclusive), defaults to todayresolution(int) (optional) The time resolution (in minutes) to retrieve. Currently only supports 5 or 30 (default)Returns:A list of pricing data for all channels. Note: This can take a very long time to return if a large amount of data is requested.get_usage(start: Optional[date], end: Optional[date], resolution: int)Get the usage data for a siteParameters:start(datetime.date) (optional) The first day to retrieve data for (inclusive), defaults to todayend(datetime.date) (optional) The last day to retrieve data for (inclusive), defaults to todayresolution(int) (optional) The time resolution (in minutes) to retrieve. Currently only supports 30 (default)Returns:A list of pricing data for all channels. Note: This can take a very long time to return if a large amount of data is requested. The documentation states it should be 30 days or less.