### Usage Point XML Schema Example
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
An example of the Usage Point XML structure, detailing service category, delivery point, and physical service location including address and geographic coordinates. This structure is used to represent metering data points.
```xml
0Main Building Electric ServiceCOMMERCIAL-RATE-AAGR-789456123Main StreetStStreetSan FranciscoCA94102US37.7749-122.4194ACCT-987654321MTR-456789
```
--------------------------------
### Handle DST and Time Zones in ESPI Data (XML, Python)
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Illustrates how to manage Daylight Saving Time (DST) rules and time zone offsets within ESPI data structures using XML examples. The Python code includes functions to decode DST rules and apply time zone and DST offsets to UTC timestamps for accurate local time representation.
```xml
0B40E2000B40B20003600-28800864001709445600360017094456001250
```
```python
from datetime import datetime, timezone, timedelta
import struct
def decode_dst_rule(hex_rule):
"""
Decode DST rule from hex format (B40E2000 format).
Returns: dict with month, week, day_of_week, time
"""
rule_bytes = bytes.fromhex(hex_rule)
# B4 = month (bits 8-11), week (bits 12-15)
# 0E = day of week (bits 0-2), time in 15-min intervals
month = (rule_bytes[0] & 0x0F)
week = (rule_bytes[1] >> 4)
day_of_week = (rule_bytes[1] & 0x07)
time_intervals = rule_bytes[2]
return {
'month': month,
'week': week,
'day_of_week': day_of_week,
'hour': (time_intervals * 15) // 60
}
def apply_timezone_offset(unix_timestamp, tz_offset_seconds, dst_active=False, dst_offset_seconds=0):
"""
Convert UTC timestamp to local time with DST consideration.
Args:
unix_timestamp: Unix epoch timestamp
tz_offset_seconds: Timezone offset from UTC in seconds (negative for west)
dst_active: Whether DST is active
dst_offset_seconds: DST offset in seconds (typically 3600)
"""
utc_time = datetime.fromtimestamp(unix_timestamp, tz=timezone.utc)
total_offset = tz_offset_seconds
if dst_active:
total_offset += dst_offset_seconds
local_time = utc_time + timedelta(seconds=total_offset)
return local_time
# Example usage
timestamp = 1709445600 # 2025-03-03 00:00:00 UTC
tz_offset = -28800 # PST: UTC-8
dst_offset = 3600 # 1 hour
dst_active = False # Before DST transition
local_time = apply_timezone_offset(timestamp, tz_offset, dst_active, dst_offset)
print(f"Local time: {local_time.strftime('%Y-%m-%d %H:%M:%S %Z')}")
# Output: Local time: 2025-03-02 16:00:00 UTC
# Decode DST rules
dst_start = decode_dst_rule("B40E2000")
print(f"DST starts: Month {dst_start['month']}, Week {dst_start['week']}, Hour {dst_start['hour']}")
# Output: DST starts: Month 3, Week 2, Hour 2
```
--------------------------------
### Validate Green Button DMD XML with Online Service
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Demonstrates how to use a `curl` command to validate Green Button Download My Data (DMD) XML files against Atom and ESPI schemas using the Green Button Alliance validator. It shows example requests and expected response formats for both valid and invalid files.
```bash
# Validate a Green Button XML file using the online validator
curl -X POST https://validator.greenbuttonalliance.org/api/validate \
-H "Content-Type: multipart/form-data" \
-F "file=@usage_data.xml" \
-F "validation_type=dmd" \
-F "schema_version=espi_1_1"
# Response format:
# {
# "valid": true,
# "version": "1.1",
# "errors": [],
# "warnings": [
# {
# "line": 45,
# "message": "Optional element
is missing",
# "severity": "warning"
# }
# ],
# "resources": {
# "usage_points": 2,
# "meter_readings": 4,
# "interval_blocks": 8,
# "reading_types": 2
# }
# }
# Example validation error response:
# {
# "valid": false,
# "errors": [
# {
# "line": 23,
# "column": 15,
# "message": "Invalid namespace: expected 'http://naesb.org/espi'",
# "severity": "error"
# },
# {
# "line": 67,
# "message": "Required element is missing in ServiceCategory",
# "severity": "error"
# }
# ],
# "warnings": []
```
--------------------------------
### Validate Green Button XML with Python
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
This Python script uses the 'requests' library to send an XML file to the Green Button Alliance validator API. It handles file uploads, schema version selection, and parses the JSON response to report validation success or failure with specific error messages. It requires the 'requests' library to be installed.
```python
import requests
import xml.etree.ElementTree as ET
def validate_green_button_xml(file_path, schema_version='espi_1_1'):
"""
Validate Green Button XML file against ESPI schema.
Args:
file_path: Path to XML file
schema_version: ESPI schema version (espi_1_1, espi_1_2)
Returns:
dict with validation results
"""
url = 'https://validator.greenbuttonalliance.org/api/validate'
try:
with open(file_path, 'rb') as f:
files = {'file': f}
data = {
'validation_type': 'dmd',
'schema_version': schema_version
}
response = requests.post(url, files=files, data=data)
response.raise_for_status()
result = response.json()
if result['valid']:
print(f"✓ Validation successful!")
print(f" Resources: {result['resources']}")
else:
print(f"✗ Validation failed with {len(result['errors'])} error(s)")
for error in result['errors']:
print(f" Line {error.get('line', 'N/A')}: {error['message']}")
if result.get('warnings'):
print(f"⚠ {len(result['warnings'])} warning(s):")
for warning in result['warnings']:
print(f" Line {warning.get('line', 'N/A')}: {warning['message']}")
return result
except requests.exceptions.RequestException as e:
return {'valid': False, 'errors': [{'message': f'Validation service error: {str(e)}'}]}
# Example usage
validation_result = validate_green_button_xml('usage_data.xml')
if validation_result['valid']:
print("Ready to process Green Button data")
else:
print("Fix errors before processing")
```
--------------------------------
### Green Button REST API - Get Interval Data
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Retrieve interval energy consumption data for a specific usage point within a date range.
```APIDOC
## GET /DataCustodian/espi/1_1/resource/Subscription/{subscriptionId}/UsagePoint/{usagePointId}/MeterReading/{meterReadingId}/IntervalBlock
### Description
Retrieves detailed interval consumption data for a specific meter reading, filtered by publication date. This endpoint provides the granular energy usage readings.
### Method
GET
### Endpoint
`/DataCustodian/espi/1_1/resource/Subscription/{subscriptionId}/UsagePoint/{usagePointId}/MeterReading/{meterReadingId}/IntervalBlock`
### Parameters
#### Path Parameters
- **subscriptionId** (string) - Required - The unique identifier for the subscription.
- **usagePointId** (string) - Required - The unique identifier for the usage point.
- **meterReadingId** (string) - Required - The unique identifier for the meter reading.
#### Query Parameters
- **published-min** (string) - Optional - The minimum publication date for filtering interval data (ISO 8601 format, e.g., `2025-01-01T00:00:00Z`).
- **published-max** (string) - Optional - The maximum publication date for filtering interval data (ISO 8601 format, e.g., `2025-01-31T23:59:59Z`).
#### Request Body
None
### Request Example
```bash
curl -X GET "https://api.utility.com/DataCustodian/espi/1_1/resource/Subscription/5/UsagePoint/1/MeterReading/1/IntervalBlock?published-min=2025-01-01T00:00:00Z&published-max=2025-01-31T23:59:59Z" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Accept: application/atom+xml"
```
### Response
#### Success Response (200 OK)
- Returns an Atom feed (`application/atom+xml`) containing `IntervalBlock` resources with detailed consumption readings, timestamps, and quantities.
#### Response Example
(Atom feed XML structure containing IntervalBlock elements with readings)
```
--------------------------------
### Map Utility Bill to ESPI Usage Summary (Python)
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Maps a utility bill object to the ESPI (Energy Services Provider Interface) usage summary format. This involves converting dates to Unix timestamps, costs to cents, and structuring line items. Dependencies include datetime objects and custom mappers.
```python
class BillToESPIMapper:
def to_unix_timestamp(self, dt):
# Placeholder for actual timestamp conversion
return int(dt.timestamp())
def to_espi_cost(self, amount):
# Placeholder for actual cost conversion to cents
return int(amount * 100)
def map_bill_to_usage_summary(self, bill):
usage_summary = {
'billToDate': self.to_espi_cost(bill.current_bill_amount),
'overallConsumptionLastPeriod': {
'value': bill.energy_consumption_kwh,
'uom': 36, # kWh
'quality': [63], # Raw data
'readInterval': 1,
'readingType': ' ', # Placeholder
'registers': [],
'unit': 'kWh'
},
'lineItems': []
}
# Add peak demand information
usage_summary['peakDemandLastPeriod'] = {
'value': int(bill.peak_demand_kw),
'uom': 38, # kW
'quality': [63], # Raw data
'readInterval': 1,
'readingType': ' ', # Placeholder
'registers': [],
'unit': 'kW'
}
# Add line items
for item in bill.line_items:
usage_summary['lineItems'].append({
'amount': self.to_espi_cost(item.amount),
'dateTime': self.to_unix_timestamp(item.date),
'note': item.description,
'rounding': 0
})
return usage_summary
# Example usage
from datetime import datetime
class UtilityBill:
def __init__(self, account_number, billing_period_start, billing_period_end, previous_bill_amount, current_bill_amount, energy_consumption_kwh, peak_demand_kw, taxes_and_fees, line_items):
self.account_number = account_number
self.billing_period_start = billing_period_start
self.billing_period_end = billing_period_end
self.previous_bill_amount = previous_bill_amount
self.current_bill_amount = current_bill_amount
self.energy_consumption_kwh = energy_consumption_kwh
self.peak_demand_kw = peak_demand_kw
self.taxes_and_fees = taxes_and_fees
self.line_items = line_items
class BillLineItem:
def __init__(self, description, amount, date):
self.description = description
self.amount = amount
self.date = date
bill = UtilityBill(
account_number='ACCT-987654321',
billing_period_start=datetime(2025, 1, 1),
billing_period_end=datetime(2025, 2, 1),
previous_bill_amount=85.32,
current_bill_amount=92.48,
energy_consumption_kwh=543,
peak_demand_kw=12.0,
taxes_and_fees=14.28,
line_items=[
BillLineItem('Energy Charges (543 kWh @ $0.10438/kWh)', 56.70, datetime(2025, 2, 1)),
BillLineItem('Demand Charges (12 kW @ $1.79/kW)', 21.50, datetime(2025, 2, 1)),
BillLineItem('Taxes and Regulatory Fees', 14.28, datetime(2025, 2, 1))
]
)
mapper = BillToESPIMapper()
espi_data = mapper.map_bill_to_usage_summary(bill)
print(f"Bill amount in ESPI format: {espi_data['billToDate']}") # 924800
print(f"Energy consumption: {espi_data['overallConsumptionLastPeriod']['value']} kWh") # 543
print(f"Number of line items: {len(espi_data['lineItems'])}") # 3
```
--------------------------------
### Python Utility Bill to ESPI Usage Summary Mapping
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Provides a Python class `BillToESPIMapper` to convert custom `UtilityBill` objects into the ESPI Usage Summary dictionary format. It handles currency conversions, timestamp generation, and structuring of consumption and line item data. Dependencies include Python's `dataclasses` and `datetime` modules.
```python
from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional
@dataclass
class BillLineItem:
description: str
amount: float
date: datetime
@dataclass
class UtilityBill:
account_number: str
billing_period_start: datetime
billing_period_end: datetime
previous_bill_amount: float
current_bill_amount: float
energy_consumption_kwh: float
peak_demand_kw: Optional[float]
line_items: List[BillLineItem]
taxes_and_fees: float
currency_code: int = 840 # USD
class BillToESPIMapper:
"""Convert utility bill data to ESPI Usage Summary format"""
COST_SCALE = 10000 # Scale factor for currency (10^-4)
@staticmethod
def to_espi_cost(amount: float) -> int:
"""Convert dollar amount to ESPI integer format"""
return round(amount * BillToESPIMapper.COST_SCALE)
@staticmethod
def to_unix_timestamp(dt: datetime) -> int:
"""Convert datetime to Unix epoch"""
return int(dt.timestamp())
@staticmethod
def map_bill_to_usage_summary(bill: UtilityBill) -> dict:
"""Map utility bill to ESPI Usage Summary structure"""
duration = int((bill.billing_period_end - bill.billing_period_start).total_seconds())
usage_summary = {
'billingPeriod': {
'duration': duration,
'start': BillToESPIMapper.to_unix_timestamp(bill.billing_period_start)
},
'billLastPeriod': BillToESPIMapper.to_espi_cost(bill.previous_bill_amount),
'billToDate': BillToESPIMapper.to_espi_cost(bill.current_bill_amount),
'costAdditionalLastPeriod': BillToESPIMapper.to_espi_cost(bill.taxes_and_fees),
'currency': bill.currency_code,
'qualityOfReading': 14, # Valid and verified
'statusTimeStamp': BillToESPIMapper.to_unix_timestamp(bill.billing_period_end),
'overallConsumptionLastPeriod': {
'powerOfTenMultiplier': 0,
'timeStamp': BillToESPIMapper.to_unix_timestamp(bill.billing_period_end),
'uom': 72, # kWh
'value': int(bill.energy_consumption_kwh)
},
'lineItems': []
}
# Add peak demand if available
if bill.peak_demand_kw:
usage_summary['currentDayMaxDemand'] = {
'powerOfTenMultiplier': 0,
```
--------------------------------
### Represent Cost and Currency in Green Button XML
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Illustrates the XML structure for representing cost and currency using integer scaling for accuracy in energy billing data. It shows how values like billing amounts, fees, and consumption are encoded with appropriate units and multipliers.
```xml
26784001704067200853200012478900250000840072456
```
--------------------------------
### Atom Elements in Green Button XML Files
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Demonstrates the structure of Green Button energy data files using the Atom Syndication Format, which serves as a container for ESPI resource representations. This XML format is essential for organizing and presenting energy usage data.
```xml
urn:uuid:97EAEBAD-1214-4A58-A3D4-A16A6DE718E1Green Button Usage Feed2025-01-15T14:30:00Zurn:uuid:DEB0A337-C1B5-4658-99BA-4688E253A99BElectric Meter - 123 Main St2025-01-01T00:00:00Z2025-01-15T14:30:00Z0
```
--------------------------------
### Java Utilities for Green Button Cost Handling
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Provides Java methods for converting between decimal currency values and the integer-scaled format used in Green Button data. It includes functions for converting to and from Green Button cost, and for formatting currency with appropriate symbols based on ISO codes.
```java
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Currency;
public class GreenButtonCostHandler {
private static final int CURRENCY_SCALE = 4; // Standard Green Button scale: 10^-4
/**
* Convert decimal currency value to Green Button integer format
*/
public static long toGreenButtonCost(BigDecimal amount) {
return amount.multiply(BigDecimal.valueOf(10000))
.setScale(0, RoundingMode.HALF_UP)
.longValue();
}
/**
* Convert Green Button integer to decimal currency value
*/
public static BigDecimal fromGreenButtonCost(long greenButtonValue) {
return BigDecimal.valueOf(greenButtonValue)
.divide(BigDecimal.valueOf(10000), 2, RoundingMode.HALF_UP);
}
/**
* Format currency with proper symbol
*/
public static String formatCurrency(long greenButtonValue, int currencyCode) {
BigDecimal amount = fromGreenButtonCost(greenButtonValue);
Currency currency;
switch (currencyCode) {
case 840: currency = Currency.getInstance("USD"); break;
case 978: currency = Currency.getInstance("EUR"); break;
case 826: currency = Currency.getInstance("GBP"); break;
default: currency = Currency.getInstance("USD");
}
return currency.getSymbol() + amount.toPlainString();
}
public static void main(String[] args) {
// Example: Converting bill amount to Green Button format
BigDecimal billAmount = new BigDecimal("85.32");
long greenButtonValue = toGreenButtonCost(billAmount);
System.out.println("Bill amount: " + billAmount + " â2122 " + greenButtonValue);
// Output: Bill amount: 85.32 â2122 853200
// Example: Reading from Green Button data
long costFromXml = 12478900L;
BigDecimal actualCost = fromGreenButtonCost(costFromXml);
System.out.println("Green Button value: " + costFromXml + " â2122 $ " + actualCost);
// Output: Green Button value: 12478900 â2122 $ 1247.89
// Example: Formatting with currency
String formatted = formatCurrency(8532000L, 840);
System.out.println("Formatted: " + formatted);
// Output: Formatted: $853.20
}
}
```
--------------------------------
### Implement OAuth 2.0 for Green Button Authorization (JavaScript)
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
This snippet demonstrates the OAuth 2.0 authorization flow for Green Button. It includes steps for redirecting users, handling callbacks with authorization codes, exchanging codes for access tokens, and refreshing expired tokens. It relies on the `fetch` API and `URLSearchParams` for making HTTP requests. Ensure secure storage of tokens.
```javascript
// Step 1: Redirect user to Data Custodian authorization endpoint
const authorizationUrl = 'https://api.utility.com/DataCustodian/oauth/authorize?' +
new URLSearchParams({
response_type: 'code',
client_id: 'YOUR_CLIENT_ID',
redirect_uri: 'https://thirdparty.com/callback',
scope: 'FB=1_3_4_5_13_14_15_16_31_32_33_34_35_36_37_38_39_40_41_44;IntervalDuration=3600;BlockDuration=monthly;HistoryLength=13'
}).toString();
// Redirect user: window.location.href = authorizationUrl;
// Step 2: Handle callback with authorization code
app.get('/callback', async (req, res) => {
const { code, error } = req.query;
if (error) {
return res.status(400).json({ error: 'Authorization failed', details: error });
}
try {
// Exchange authorization code for access token
const tokenResponse = await fetch('https://api.utility.com/DataCustodian/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64')
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: 'https://thirdparty.com/callback'
})
});
const tokens = await tokenResponse.json();
// Store tokens.access_token, tokens.refresh_token securely
res.json({ success: true, resource_uri: tokens.resourceURI });
} catch (err) {
res.status(500).json({ error: 'Token exchange failed', details: err.message });
}
});
// Step 3: Refresh expired access token
async function refreshAccessToken(refreshToken) {
const response = await fetch('https://api.utility.com/DataCustodian/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64')
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken
})
});
return await response.json();
}
```
--------------------------------
### XML Schema for ESPI Usage Summary Resource
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Defines the structure for representing utility billing data in the ESPI Usage Summary format. It includes details on billing periods, costs, consumption, and line item charges. This schema is crucial for standardized data exchange in the Green Button ecosystem.
```xml
267840017040672008532000924750012500008401417067456000170674560072543017094240007258701705348800381256700001706745600Energy Charges (543 kWh @ $0.10438/kWh)021500001706745600Demand Charges (12 kW @ $1.79/kW)14275001706745600Taxes and Regulatory Fees
```
--------------------------------
### JavaScript Usage Point and Service Location Mapper
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
A JavaScript class `ServiceLocationMapper` with static methods to create Usage Point objects from account data and extract service location details from a Usage Point object. It facilitates the integration of service location data into the Usage Point structure.
```javascript
// JavaScript mapping helper
class ServiceLocationMapper {
/**
* Create Usage Point with service location mapping
*/
static createUsagePointWithLocation(accountData) {
return {
usagePoint: {
serviceCategory: { kind: accountData.serviceType || 0 },
serviceDeliveryPoint: {
name: accountData.serviceName,
tariffProfile: accountData.rateSchedule,
customerAgreement: accountData.agreementId
},
serviceLocation: {
mainAddress: {
streetDetail: {
number: accountData.address.streetNumber,
name: accountData.address.streetName,
suffix: accountData.address.streetSuffix,
type: accountData.address.streetType
},
townDetail: {
name: accountData.address.city,
stateOrProvince: accountData.address.state,
code: accountData.address.zipCode,
country: accountData.address.country || 'US'
}
},
geoInfoReference: accountData.coordinates ? {
latitude: accountData.coordinates.lat,
longitude: accountData.coordinates.lon
} : null
},
accountId: accountData.accountNumber,
meterSerialNumber: accountData.meterSerial
}
};
}
/**
* Extract service location from Usage Point
*/
static extractServiceLocation(usagePointXml) {
// Parse XML and extract location
const location = {
address: `${usagePointXml.serviceLocation.mainAddress.streetDetail.number} ` +
`${usagePointXml.serviceLocation.mainAddress.streetDetail.name} ` +
`${usagePointXml.serviceLocation.mainAddress.streetDetail.suffix}`,
city: usagePointXml.serviceLocation.mainAddress.townDetail.name,
state: usagePointXml.serviceLocation.mainAddress.townDetail.stateOrProvince,
zip: usagePointXml.serviceLocation.mainAddress.townDetail.code,
coordinates: usagePointXml.serviceLocation.geoInfoReference
};
return location;
}
}
// Example usage
const accountData = {
serviceName: 'Main Building Electric Service',
serviceType: 0,
rateSchedule: 'COMMERCIAL-RATE-A',
agreementId: 'AGR-789456',
accountNumber: 'ACCT-987654321',
meterSerial: 'MTR-456789',
address: {
streetNumber: '123',
streetName: 'Main',
streetSuffix: 'St',
streetType: 'Street',
city: 'San Francisco',
state: 'CA',
zipCode: '94102',
country: 'US'
},
coordinates: {
lat: 37.7749,
lon: -122.4194
}
};
const usagePoint = ServiceLocationMapper.createUsagePointWithLocation(accountData);
console.log(JSON.stringify(usagePoint, null, 2));
```
--------------------------------
### Apply Power-of-Ten Multipliers in ESPI Data (XML, JavaScript)
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Demonstrates how to represent and interpret scaled integer values in ESPI data using power-of-ten multipliers. The JavaScript code provides helper functions to apply and remove these multipliers, useful for both reading and preparing ESPI data for energy consumption and costs.
```xml
36001704067200123456-272452300840-4
```
```javascript
// JavaScript helper for applying multipliers
function applyMultiplier(value, powerOfTen) {
return value * Math.pow(10, powerOfTen);
}
function removeMultiplier(decimalValue, powerOfTen) {
return Math.round(decimalValue * Math.pow(10, -powerOfTen));
}
// Reading values from ESPI
const intervalReading = {
value: 123456,
powerOfTenMultiplier: -2,
uom: 72 // kWh
};
const actualKwh = applyMultiplier(intervalReading.value, intervalReading.powerOfTenMultiplier);
console.log(`Energy consumption: ${actualKwh} kWh`); // 1234.56 kWh
// Preparing values for ESPI
const costInDollars = 45.23;
const powerOfTen = -4;
const costInteger = removeMultiplier(costInDollars, powerOfTen);
console.log(`ESPI cost value: ${costInteger}`); // 452300
```
--------------------------------
### Green Button REST API OAuth Authentication and Data Retrieval
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Illustrates the process of interacting with Green Button Data Custodian REST APIs. It covers obtaining an OAuth access token, retrieving usage points for a subscription, and fetching interval data for a specific usage point and date range. Requires a valid client ID and secret for token exchange.
```bash
# Step 1: Obtain OAuth access token
curl -X POST https://api.utility.com/DataCustodian/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE_FROM_USER_AUTHORIZATION" \
-d "redirect_uri=https://thirdparty.com/callback"
# Response:
# {
# "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
# "token_type": "Bearer",
# "expires_in": 3600,
# "refresh_token": "8xLOxBtZp8",
# "scope": "FB=1_3_4_5_13_14_15_16_31_32_33_34_35_36_37_38_39_40_41_44;IntervalDuration=3600"
# }
# Step 2: Retrieve usage data for a specific subscription
curl -X GET https://api.utility.com/DataCustodian/espi/1_1/resource/Subscription/5/UsagePoint \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Accept: application/atom+xml"
# Step 3: Get interval data for a specific usage point and date range
curl -X GET "https://api.utility.com/DataCustodian/espi/1_1/resource/Subscription/5/UsagePoint/1/MeterReading/1/IntervalBlock?published-min=2025-01-01T00:00:00Z&published-max=2025-01-31T23:59:59Z" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Accept: application/atom+xml"
# Response includes interval readings with timestamps and consumption values
```
--------------------------------
### Green Button XML Usage Point for Aggregated Data
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
This XML snippet demonstrates the structure for representing an aggregated Usage Point in Green Button data. It includes details about the service category, status, role flags indicating aggregated data, and a ServiceDeliveryPoint name. It also shows a MeterReading entry with aggregated Interval data, specifying daily aggregation and a total consumption value.
```xml
urn:uuid:AFC97598-8DD8-43A1-A8E0-D6F8C3E5F2A1Aggregated Usage Feed - Corporate Campusurn:uuid:B1C2D3E4-F5A6-4B7C-8D9E-0F1A2B3C4D5ECorporate Campus - Aggregated Electric Usage0112Aggregated - Buildings 1-5urn:uuid:C2D3E4F5-A6B7-4C8D-9E0F-1A2B3C4D5E6F864001704067200864001704067200125000-27212
```
--------------------------------
### Green Button REST API - Retrieve Usage Data
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
Retrieve energy usage data for a specific subscription, including usage points.
```APIDOC
## GET /DataCustodian/espi/1_1/resource/Subscription/{id}/UsagePoint
### Description
Retrieves a list of usage points associated with a given subscription ID. This is typically the first step in accessing detailed energy data for a customer.
### Method
GET
### Endpoint
`/DataCustodian/espi/1_1/resource/Subscription/{id}/UsagePoint`
### Parameters
#### Path Parameters
- **id** (string) - Required - The unique identifier for the subscription.
#### Query Parameters
None
#### Request Body
None
### Request Example
```bash
curl -X GET https://api.utility.com/DataCustodian/espi/1_1/resource/Subscription/5/UsagePoint \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Accept: application/atom+xml"
```
### Response
#### Success Response (200 OK)
- Returns an Atom feed (`application/atom+xml`) containing `UsagePoint` resources.
#### Response Example
(Atom feed XML structure containing UsagePoint elements)
```
--------------------------------
### Generate Persistent UUIDs for Green Button Resources (Python)
Source: https://context7.com/context7/greenbuttonalliance_developer-resources/llms.txt
This Python function generates Version 5 UUIDs using SHA-1 hashing, ensuring that the same input parameters consistently produce the same UUID. This is useful for creating persistent and reproducible identifiers for Green Button resources. It requires the `uuid` and `hashlib` libraries.
```python
import uuid
import hashlib
# Define namespace UUID for Green Button (example - use your organization's namespace)
GREEN_BUTTON_NAMESPACE = uuid.UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
def generate_persistent_uuid(resource_type, unique_identifier):
"""
Generate a Version 5 UUID for a Green Button resource.
Args:
resource_type: Type of resource (e.g., 'UsagePoint', 'MeterReading')
unique_identifier: Unique identifier from source system (e.g., meter ID)
Returns:
UUID string in URN format
"""
# Combine resource type and identifier
name = f"{resource_type}:{unique_identifier}"
# Generate Version 5 UUID using SHA-1
resource_uuid = uuid.uuid5(GREEN_BUTTON_NAMESPACE, name)
return f"urn:uuid:{resource_uuid}"
# Example usage
usage_point_id = generate_persistent_uuid('UsagePoint', 'MTR-12345-67890')
print(f"UsagePoint UUID: {usage_point_id}")
# Output: UsagePoint UUID: urn:uuid:a1b2c3d4-e5f6-5789-a1b2-c3d4e5f67890
meter_reading_id = generate_persistent_uuid('MeterReading', 'MTR-12345-67890-2025-01')
print(f"MeterReading UUID: {meter_reading_id}")
# Output: MeterReading UUID: urn:uuid:b2c3d4e5-f6a7-5890-b2c3-d4e5f6a78901
# Verify persistence - same input always produces same UUID
duplicate_id = generate_persistent_uuid('UsagePoint', 'MTR-12345-67890')
assert usage_point_id == duplicate_id # True
```