Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions specification/energy-credentials/meter-data-vc/attributes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
openapi: 3.1.1
info:
title: Meter Data Credential Schema
version: 1.0.0
description: >
OpenAPI 3.1.1 schema for the Meter Data Verifiable Credential.
Contains historical time-series interval meter readings aligned with
Green Button (ESPI/NAESB) semantics. Issued by the utility; consumed
by trading apps for demand forecasting.

components:
schemas:

MeterDataCredential:
type: object
description: >
W3C Verifiable Credential wrapping historical meter reading data.
required:
- "@context"
- id
- type
- issuer
- issuanceDate
- credentialSubject
properties:
"@context":
type: array
items:
type: string
contains:
const: "https://www.w3.org/2018/credentials/v1"
minItems: 2
id:
type: string
format: uri
pattern: "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
description: Unique identifier for the credential in URN UUID format
type:
type: array
items:
type: string
contains:
const: MeterDataCredential
minItems: 2
issuer:
$ref: '#/components/schemas/UtilityIssuer'
issuanceDate:
type: string
format: date-time
description: Date and time when the credential was issued
expirationDate:
type: string
format: date-time
description: Optional expiration date of the credential
credentialStatus:
$ref: '#/components/schemas/CredentialStatus'
credentialSubject:
$ref: '#/components/schemas/MeterDataSubject'
proof:
$ref: '#/components/schemas/Proof'

UtilityIssuer:
type: object
required:
- id
- name
- licenseNumber
properties:
id:
type: string
format: uri
description: DID of the issuing distribution utility
name:
type: string
minLength: 1
description: Name of the distribution utility
licenseNumber:
type: string
minLength: 1
description: Regulatory license number issued by the local energy regulator

CredentialStatus:
type: object
required:
- id
- type
description: Revocation status information for the credential
properties:
id:
type: string
format: uri
description: URL to query the revocation status via DeDi registry
type:
type: string
const: dediregistry
description: Type of status check mechanism (DeDi Registry)

Proof:
type: object
required:
- type
- created
- verificationMethod
- proofPurpose
- proofValue
properties:
type:
type: string
description: "Cryptographic signature type (e.g., Ed25519Signature2020)"
created:
type: string
format: date-time
description: Timestamp when the proof was created
verificationMethod:
type: string
format: uri
description: URI of the verification method / public key
proofPurpose:
type: string
enum:
- assertionMethod
- authentication
description: Purpose of the proof
proofValue:
type: string
minLength: 1
description: The cryptographic signature value

# ── credentialSubject ──────────────────────────────────────────

MeterDataSubject:
type: object
description: >
Historical meter reading data for a single meter, using Green Button
(ESPI/NAESB) semantics.
required:
- id
- meterNumber
- serviceKind
- timeZone
- readingType
- coveragePeriod
- intervalBlocks
properties:
id:
type: string
format: uri
description: DID of the customer / credential subject
meterNumber:
type: string
minLength: 1
maxLength: 50
description: >
Meter serial number (links to the physical meter;
reused from Utility Customer Credential)
serviceKind:
$ref: '../../external/schema/green-button/attributes.yaml#/components/schemas/ServiceKind'
timeZone:
type: string
description: >
IANA time-zone identifier for the meter location
(e.g., "Asia/Kolkata"). Critical for demand-forecasting models
that need local solar time.
examples:
- "Asia/Kolkata"
- "America/New_York"
readingType:
$ref: '../../external/schema/green-button/attributes.yaml#/components/schemas/ReadingType'
coveragePeriod:
type: object
description: >
Summary date range of the data contained in this credential.
required:
- start
- end
properties:
start:
type: string
format: date-time
description: Start of the coverage period (ISO 8601)
end:
type: string
format: date-time
description: End of the coverage period (ISO 8601)
intervalBlocks:
type: array
items:
$ref: '../../external/schema/green-button/attributes.yaml#/components/schemas/IntervalBlock'
minItems: 1
description: >
Array of interval blocks containing the actual meter readings.
Each block covers a contiguous time span.
154 changes: 154 additions & 0 deletions specification/energy-credentials/meter-data-vc/context.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"schema": "https://schema.org/",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"espi": "http://naesb.org/espi#",
"meter": "https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/meter-data-vc/context.jsonld#",

"MeterDataCredential": {
"@id": "meter:MeterDataCredential",
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"meterNumber": {
"@id": "meter:meterNumber",
"@type": "xsd:string"
},
"serviceKind": {
"@id": "espi:ServiceKind",
"@type": "xsd:string"
},
"timeZone": {
"@id": "meter:timeZone",
"@type": "xsd:string"
},
"readingType": {
"@id": "espi:ReadingType",
"@type": "@id",
"@context": {
"@version": 1.1,
"@protected": true,
"commodity": {
"@id": "espi:CommodityKind",
"@type": "xsd:string"
},
"flowDirection": {
"@id": "espi:FlowDirectionKind",
"@type": "xsd:string"
},
"uom": {
"@id": "espi:UnitOfMeasure",
"@type": "xsd:string"
},
"powerOfTenMultiplier": {
"@id": "espi:UnitMultiplierKind",
"@type": "xsd:integer"
},
"accumulationBehaviour": {
"@id": "espi:AccumulationBehaviourKind",
"@type": "xsd:string"
},
"intervalLength": {
"@id": "espi:intervalLength",
"@type": "xsd:integer"
}
}
},
"coveragePeriod": {
"@id": "meter:coveragePeriod",
"@type": "@id",
"@context": {
"@version": 1.1,
"@protected": true,
"start": {
"@id": "meter:start",
"@type": "xsd:dateTime"
},
"end": {
"@id": "meter:end",
"@type": "xsd:dateTime"
}
}
},
"intervalBlocks": {
"@id": "espi:IntervalBlock",
"@type": "@id",
"@container": "@set",
"@context": {
"@version": 1.1,
"@protected": true,
"interval": {
"@id": "espi:DateTimeInterval",
"@type": "@id",
"@context": {
"@version": 1.1,
"@protected": true,
"start": {
"@id": "meter:start",
"@type": "xsd:dateTime"
},
"duration": {
"@id": "meter:duration",
"@type": "xsd:integer"
}
}
},
"intervalReadings": {
"@id": "espi:IntervalReading",
"@type": "@id",
"@container": "@set",
"@context": {
"@version": 1.1,
"@protected": true,
"timePeriod": {
"@id": "espi:DateTimeInterval",
"@type": "@id",
"@context": {
"@version": 1.1,
"@protected": true,
"start": {
"@id": "meter:start",
"@type": "xsd:dateTime"
},
"duration": {
"@id": "meter:duration",
"@type": "xsd:integer"
}
}
},
"value": {
"@id": "espi:value",
"@type": "xsd:integer"
}
}
}
}
}
}
},

"UtilityIssuer": {
"@id": "meter:UtilityIssuer",
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"name": {
"@id": "schema:name",
"@type": "xsd:string"
},
"licenseNumber": {
"@id": "meter:licenseNumber",
"@type": "xsd:string"
}
}
}
}
}
Loading