Open Power Quality

Open Power Quality

  • Documentation
  • Opportunities
  • News

›Developer Guide: OPQ Cloud

Introduction

  • Motivation for OPQ
  • A beginner's guide to power quality
  • OPQ System Architecture
  • OPQ Information Architecture
  • Related Work
  • Bibliography

User Guide

  • OPQ Box
  • OPQ Cloud

Developer Guide: OPQ Box

  • Overview
  • Hardware Design
  • Software Design
  • Manufacturing

Developer Guide: OPQ Cloud

  • Overview
  • Installation
  • Data Model
  • View
  • Mauka
  • Makai
  • Health
  • Health v2
  • Box Update Server
  • MongoDB
  • Protocol
  • Port Map
  • Docker
  • Cloud Migration

Developer Guide: Misc

  • Documentation
  • VM & Sim
  • Bibliography
  • Emilia SSH

Other

  • Roadmap
  • R&D Opportunities
  • Agile Power Monitoring for UH
  • G1 Pilot Study (2014)

OPQ Data Model

At the core of the OPQ system lies a centralized MongoDB database. The majority of this data is managed by the OPQMauka and OPQMakai systems, though some of it (Locations, Regions, Users) is managed by OPQ View, and the Health collection is managed by the Health process.

The set of MongoDB collections and their relationships constitutes the OPQ Data Model. Here's an overview of the collections:

CollectionDescription
box_eventsHigh-fidelity data associated with a single box.
BoxOwnersA bi-directional mapping from OPQ Boxes to the Users that have an "ownership" role on them.
eventsHigh fidelity data (potentially across multiple boxes) when measurement values trigger further data collection.
fs.files, fs.chunksImplements GridFS for storage of binary waveform data.
healthTimestamped data indicating if OPQ Boxes and services appear to be running.
locationsDefinitions for locations in terms of latitude and longitude.
measurementsShort term, low fidelity OPQBox data.
opq_boxesInformation about individual OPQBoxes, such as its current (and prior) locations.
regionsImplements aggregations of locations and regions.
system_statsTimestamped documents with near-real time information about the state of the system.
trendsLong term, aggregated OPQBox trend data.
UserProfilesInformation about users: username, first and last name, and role (user or admin).

Naming Conventions

The OPQ system is comprised of a multitude of different tools, libraries, and frameworks. In order to minimize confusion, we mostly follow a basic set of naming conventions for our collections and documents that we feel will keep things as simple as possible:

  • All collection names and documents fields are in lower-case
  • Collection names should always be plural
  • Use underscores over camel-case to separate words

Box Events

The box_events collection provides the event meta-data for a given OPQBox.

As an event can be associated with multiple OPQBoxes, it is therefore important to understand that there can be (and often are) multiple box_event documents with the same event_id.

Query on the event_id and box_id fields to find data for a given OPQBox for a specific event.

FieldTypeDescription
event_idIntegerThe event_id generated by an events document.
box_idStringThe OPQBox from which this data was produced.
event_start_timestamp_msIntegerUnix timestamps indicating the requested start time for the high fidelity data.
event_end_timestamp_msIntegerUnix timestamps indicating the requested end time for the high fidelity data.
window_timestamps_ms[Integer]An array of Unix timestamps that correlate with every 2000 samples (10 grid cycles) of recorded box data. This can be useful for debugging purposes, as we can determine the continuity of box data.
locationStringLocation slug see Location for details.
data_fs_filenameStringIndicates the GridFS filename that holds the box_event's actual raw waveform data.

Supplemental indexing: event_start_time_ms and box_id form a unique composite index.

Box Owners

The BoxOwners collection provides a bi-directional mapping between OPQ Boxes and the users who have ownership over them.

FieldTypeDescription
usernameStringThe box owner's username (email address).
boxIdStringThe Box owned by this user. A string such as "1", "2" etc. Not the documentID!

Supplemental indexing: none.

Events

The events collection provides access to high fidelity waveform data that was retrieved from OPQ Boxes in response to non-nominal measurements.

FieldTypeDescription
event_idIntegerA unique integer value generated for each event.
descriptionStringIndicates additional information about the event
boxes_triggered[String]A list of all OPQBoxes associated with the given event - however it is important to note that this does not always correspond to all of the OPQBoxes for which we have received actual data from for the event.
boxes_received[String]List of all OPQBoxes from which high fidelity data was received for the event
latencies_ms[Integer]an array of timestamps (milliseconds since epoch) indicating the time when data from each OPQBox was received. Maintains a 1 to 1 correlation with boxes_received.
target_event_start_timestamp_msIntegerUnix timestamps indicating the requested start time for the high fidelity data.
target_event_end_timestamp_msIntegerUnix timestamps indicating the requested end time for the high fidelity data

Supplemental indexing: event_id is a unique index, target_event_start_time_ms is an index.

fs.files, fs.chunks

GridFS is a MongoDB specification for storing large documents. As an OPQBox can collect a very large amount of data for each given event (often exceeding the 16 MB MongoDB document size limit), we've opted to utilize GridFS to store our high-fidelity data.

At its core, GridFS is a very simple system consisting of two collections, fs.files and fs.chunks.

The fs.files collection stores file metadata:

FieldTypeDescription
filenameStringGenerated by GridFS, corresponds to the box_event's data_fs_filename field,
lengthIntegerGenerated by GridFS
chunkSizeIntegerGenerated by GridFS
uploadDateDateGenerated by GridFS
md5StringGenerated by GridFS
metadata.event_idIntegerAdded by Makai, used to find the corresponding box_event document.
metadata.box_idStringAdded by Makai, used to find the corresponding box_event document.
metadata.incident_idStringAdded by Mauka, used to find the corresponding incident document.

Supplemental indexing: none

Note: The GridFS specification requires the metadata field be used to store any external information for the given file document. See GridFS files.metadata for more information.

The fs.chunks collection has the following structure:

FieldTypeDescription
files_idObjectIdObject ID.
nIntegerLength
dataBinaryThe data.

Supplemental indexing: none

Health

The OPQ Health service creates documents representing its findings on the current health of the system with the following structure:

FieldTypeDescription
timestampDateEach entry has a timestamp, which is a UTC string indicating the time at which the entry was generated.
serviceStringIndicates the OPQ Service whose status is being described in this entry. Service should be one of the following: "box", "mauka", "makai", "view", "mongodb" and "health". Yes, OPQHealth reports on its own health!
serviceIDStringFor some services, such as "box", additional identifying information is required. The serviceID field provides that information. In the case of OPQBoxes, the serviceID field provides the boxID.
statusStringStatus is either "up" or "down".
infoStringInfo is an optional field that can be used by OPQHealth to provide additional information about an entry.

Supplemental indexing: timestamp.

Incidents

The Incident entity is under construction and not yet available.

The incidents collection contains documents that classify one or more events. An incident represents a deviation from nominal values for either frequency, voltage, or THD that has been classified.

FieldTypeDescription
incident_idIntegerA unique integer representing the incident
event_idStringEvent id
box_idStringBox id
start_timestamp_msIntegerStart of the incident (ms since epoch)
end_timestamp_msIntegerEnd of the incident (ms since epoch)
locationStringLocation slug
measurement_typeStringOne of [VOLTAGE, FREQUENCY, THD, or TRANSIENT]
deviation_from_nominalFloatAbsolute value of measurement deviation from nominal
measurements[Measurement]Copied from event
gridfs_filenameStringFilename of trimmed waveform copied from event
classifications[Classification]List of classifications that can be applied to incident (see table below)
ieee_durationStringA string indicating one of the standard IEEE durations associated with this incident (see table below)
annotations[Annotation]List of annotations associated with this incident
metadataObjectKey-Value pairs providing meta-data for this incident

Supplemental indexing: box_id, location, start_timestamp_ms, measurement_type, classifications

Various organization such as IEEE, ITIC, CBEMA, and SEMI have proposed standardized terminology for classifying power quality deviations. The following two tables cover the classifications based on these standards. Note that the standards overlap, so an incident could have multiple, simultaneous classifications (such as both ITIC_PROHIBITED and VOLTAGE_SWELL, or both SEMI_F47_VIOLATION and VOLTAGE_SAG). For clarity, we indicate the type of incident and the duration of the incident separately, except in the case of SEMI_F47_VIOLATION, where the durations do not conform to the IEEE categories and so are included in the classication.

ClassificationDescription
EXCESSIVE_THDExceeds IEEE 1159 recommendations for THD (5% over 200 ms windows).
ITIC_PROHIBITEDVoltage observed in the ITIC prohibited region.
ITIC_NO_DAMAGEVoltage observed in the ITIC no damage region.
VOLTAGE_SWELLVoltage greater than 1.1 pu
VOLTAGE_SAGVoltage between 0.1 - 0.9 pu
VOLTAGE_INTERRUPTIONVoltage less than 0.1 pu
FREQUENCY_SWELLFrequency greater than 60.1 Hz
FREQUENCY_SAGFrequency between 58 Hz and 59.9 Hz
FREQUENCY_INTERRUPTIONFrequency less than 58 Hz
SEMI_F47_VIOLATIONVoltage observed at 0.5 pu for more than 200ms, 0.7 pu for more than 0.5 seconds, or 0.8 pu for more than 1 second.

Note: pu stands for "per unit" and 1pu = nominal. In the U.S. 1pu = 120V.

The following table classifies the duration according to standard IEEE terminology for durations. Note that the precise duration of the incident can be determined by subtracting start_timestamp_ms from end_timestamp_ms.

IEEE DurationDescription
INSTANTANEOUSA duration between 0.5 and 30 cycles
MOMENTARYA duration between 30 cycles and 3 seconds
TEMPORARYA duration between 3 seconds and 1 minute
SUSTAINEDA duration greater than 1 minute

Locations

The locations collection provides entities that define locations that can be associated with OPQ Boxes, Trends, Events, and other entities in the system.

FieldTypeDescription
slugStringA unique, human-friendly string identifier.
coordinatesArrayContains longitude and latitude coordinates in that order.
descriptionStringA description of the location.

Supplemental indexing: slug is a unique index, description is a unique index.

Note that the coordinates array must list longitude first, then latitude. See this StackOverflow Question for more details. Mongo has great support for GeoSpatial queries, so this will be fun to have.

Location slugs should be considered permanent once defined. Since these slugs have the potential to appear in other documents throughout the database, you will have to guarantee that the location does not appear anywhere else in the database in order to delete it.

Likewise, you should not change the coordinate values willy-nilly. Only change them if they incorrectly specify the intended location.

Measurements

The measurements collection provides low-fidelity OPQBox snapshot data for a specific moment in time. Documents in this collection are produced at a very rapid rate; OPQ Makai requests data from each OPQ Box at a rate of six times per second. As such, each measurement document can essentially be thought of as an OPQBox "heartbeat", providing a timestamp and some additional low-fidelity data. Documents are persisted in the collection for a period of 24 hours before expiring.

FieldTypeDescription
box_idStringThe Box ID.
timestamp_msIntegerThe Unix UTC timestamp in milliseconds.
voltageFloatRMS voltage
frequencyFloatFrequency
thdFloatTotal Harmonic Distortion (over this measurement window)
expireAtDateCurrently set to 24 hours.

Supplemental indexing: box_id and timestamp_ms are a unique composite index.

OPQ Boxes

The opq_boxes collection provides information about each individual OPQBox in the system.

FieldTypeDescription
box_idStringA unique string identifier for the OPQBox. This value is always referenced throughout the data model when we need to store a box_id value within a document. Currently they are strings like "1", "2", "3".
nameStringA unique user-friendly string identifier for the OPQBox. Unlike the box_id value, which is often used internally throughout the data model, the name value should be thought of as the external representation of the OPQBox.
descriptionStringOptional: can be used to further describe an OPQBox.
calibration_constantFloatA box-specific value that is used to adjust the values returned by the analog-to-digital converter chip so that we get accurate voltage and frequency values.
locationStringA location slug that identifies the current location of this box.
location_start_time_msIntegerA UTC millisecond time stamp indicating the time that data from the current location began being transmitted.
location_archiveArrayContains objects with fields location and location_start_time_ms. This provides a historical record of the locations associated with this box.
public_keyStringA 32 byte key used for CurveZMQ authentication.

Supplemental indexing: box_id is a unique index, name is a unique index.

Regions

“Regions” represent aggregations of Locations. Conceptually, a region consists of a region name along with a list of locations that are included in that region. This is implemented via a bi-directional table called "regions":

FieldTypeDescription
regionSlugStringThe unique identifier for a region.
locationSlugStringThe unique identifer for the location associated with this region.

Supplemental indexing: none.

Note that regions do not have a "description". Their slug should be self-descriptive, such as a city name (i.e. "Kailua, HI") or zip code (i.e. "96734"). Note that the relationship is many-to-many: a region can be associated with multiple locations, and a location can be associated with multiple regions.

You can create a hierarchy of regions. For example, you can specify 5 locations as being in "96734", and those same 5 locations (as well as many others) can be included in the region named "Hawaii".

Region and location slugs together constitute a single namespace (i.e. you can’t have two locations or two regions both called “96734”, nor can you have a location called “96734" and a region also called “96734”).

System Stats

The SystemStats collection consists of a single timestamped document which provides "near-real time" information about the state of the system. The goal of the SystemStats collection is to facilitate system scalability: a server-side cron job can update the SystemStats document once every 10 seconds, and then all connected clients will be updated with the revised document that summarizes the most recent state of the system. This is preferable to clients retrieving individual Measurements documents, for example.

FieldTypeDescription
timestampDateThe time when this data was collected.
events_countIntegerThe total number of events in the database.
events_count_todayIntegerThe total number of events created so far today.
box_events_countIntegerThe total number of box_events in the database.
box_events_count_todayIntegerThe total number of box_events created so far today.
measurements_countIntegerThe total number of measurements in the database.
measurements_count_todayIntegerThe total number of measurements created so far today.
trends_countIntegerThe total number of trends in the database.
trends_count_todayIntegerThe total number of trends created so far today.
opq_boxes_countIntegerThe total number of opq_boxes in the database.
users_countIntegerThe total number of users.
box_trend_statsArrayEach element is an object with fields boxId (the box ID), firstTrend (the timestamp of the earliest trend collected for this box), lastTrend (the timestamp of the most recent trend associated with this box), and totalTrends (the total number of trends associated with this box)

Supplemental indexing: none.

Trends

The trends collection provides OPQBox measurements of voltage, frequency, and THD that are persisted indefinitely. Each trend document represents data aggregated over a one minute data collection window for an individual OPQBox. Trend data is essentially a "roll-up" of the measurement data associated with a box.

FieldTypeDescription
box_idStringThe box ID.
timestamp_msIntegerThe Unix UTC timestamp.
locationStringThe location slug indicating the place this box was located at the time of data collection.
voltageObjectAn object with fields min, max, and average. Each are floats, representing the voltage values calculated for the minute preceding this timestamp.
frequencyObjectAn object with fields min, max, and average. Each are floats, representing the frequency values calculated for the minute preceding this timestamp.
thdObjectAn object with fields min, max, and average. Each are floats, representing the THD values calculated for the minute preceding this timestamp.

Supplemental indexing: box_id and timestamp_ms are a composite index.

Users

Users are represented in OPQ by three collections: the Users collection (maintained by Meteor, which provides password and basic account information, which is not shown below), UserProfiles (additional profile information, shown below), and BoxOwners (which provides a two-way mapping between OPQ Boxes and their owner(s), discussed elsewhere on this page).

Here's the UserProfile collection structure:

FieldTypeDescription
usernameStringThe user's username, which is their email address.
firstNameStringTheir first name.
lastNameStringThe user's last name.
roleStringCurrently, the defined roles are "user" and "admin".
phoneStringTheir phone number + provider
unseen_notificationsBoolTurns true when user has new notifications they haven't seen yet.
notification_preferencesObjectFields:
- text and email are booleans and represents how user wants to receive notifications.
- max_per_day is a string and represents how often user wants to be sent notifications. It can be set to 'once a day', 'once an hour', or 'never'.
- notification_types is an array of notification types the user wants to receive. All notification types users can subscribe to are stored in an array in the Notification collection as notificationTypes.

Supplemental indexing: username is a unique index.

Notifications

A notification document is created whenever something of interest happens and maps to users that are interested in that particular notification type. Notification documents are removed from db after a week.

Here's the UserProfile collection structure:

FieldTypeDescription
usernameStringThe username of the user that is associated with this notification doc
typeStringThe type of notification. i.e. 'system service down'. UserProfiles collection stores all the notification types a user is subscribed to in an array of strings.
timestampDateTime when the notification doc was created.
dataObjectFields:
- summary is a string that provides additional info about the event that triggered it
More fields to be added as more notification types are added.
deliveredBooleanTurns true once the notification is sent to the user it is associated with.

In OPQ View, only admins are able to define entities such as users, locations, regions, and OPQ Boxes. Users basically have only "read access" to the data in the system. (This will change in future when we provide the ability for users to annotate events and incidents.)

← InstallationView →
  • Naming Conventions
  • Box Events
  • Box Owners
  • Events
  • fs.files, fs.chunks
  • Health
  • Incidents
  • Locations
  • Measurements
  • OPQ Boxes
  • Regions
  • System Stats
  • Trends
  • Users
  • Notifications
Open Power Quality
Documentation Quick Links
OverviewOPQ Box User GuideOPQ View User GuideAgile Power Monitoring for UHRoadmap
Community
SlackTwitterNewsPublic OPQ CloudContact Us
Development
GitHubProject BoardsDeveloper TeamOpportunities

Open Power Quality is sponsored by:
Collaborative Software Development Laboratory, University of Hawaii
Department of Information and Computer Sciences, University of Hawaii
Department of Electrical Engineering, University of Hawaii