Files
airmq-android/app/src/main/graphql/schema.graphqls
beetzung df4e6f9c56 feat(dashboard): city average GraphQL, metrics repository, and wiring
Adds CityAverage operations and DashboardMetricsRepository, extends CityService, updates dashboard contract/VM and chart mapping, refreshes schema, tweaks map screen and Apollo logging, and adds debug manifest.

Made-with: Cursor
2026-04-06 17:02:19 +02:00

1497 lines
20 KiB
GraphQL

"""
A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.
"""
scalar DateTime
"""
The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSONObject
"""
Roles that can be held by a user. Used by @hasRole directive.
"""
enum Role {
visitor
appUser
apiUser
webUser
areaAdmin
admin
}
enum TimeFilter {
HOUR
DAY
WEEK
MONTH
}
enum Sensor {
DUST
TEMPERATURE
HUMIDITY
PRESSURE
RADIOACTIVITY
WATERLEVEL
}
enum MapLayer {
AQI
PM1
PM25
PM10
Temp
Hum
Press
Radio
}
type City {
_id: String
countryCode: String
cityName: CityName
areaId: String
areaName: String
latitude: Float
longitude: Float
locationCount: Int
}
"""
The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
"""
scalar Float
"""
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
"""
scalar Int
type CityName {
be: String
ru: String
en: String
ge: String
pl: String
alt: [String]
}
type Area {
_id: String
countryCode: String
areaName: AreaName
}
type AreaName {
be: String
ru: String
en: String
}
type LatLng {
lat: Float
lng: Float
}
type CalSession {
_id: String
deviceList: [String]
startedBy: String
refDevice: String
startTime: DateTime
stopTime: DateTime
}
type CalReport {
startTime: DateTime
}
input CalStartInput {
ids: [String]!
refDevice: String
}
input CalStopInput {
sessId: String!
}
type Widget {
lName: String
dpHeight: Int
widgetId: Int
lat: Float
lon: Float
position: Int
type: WidgetType
whatToShow: String
zoom: Float
deviceId: String
locationId: String
filter: String
sensor: String
active: Boolean
}
"""
The `Boolean` scalar type represents `true` or `false`.
"""
scalar Boolean
input AddWidgetInput {
_id: String!
wgt: WidgetInput
}
input MoveWidgetInput {
_id: String
widgetId: Int
updown: Upndown
}
input RemoveWidgetInput {
_id: String
widgetId: Int
}
input WidgetInput {
widgetId: Int
lat: Float
lon: Float
position: Int
type: WidgetType!
whatToShow: String
zoom: Float
deviceId: String
locationId: String
filter: TimeFilter
sensor: Sensor
dpHeight: Int @deprecated(reason: "No longer used.")
}
enum WidgetType {
CHART
MAP
NEWS
}
enum Upndown {
UP
DOWN
}
type Device {
_id: String
model: DeviceModel
Sensorcom: Boolean
Narodmon: Boolean
sleepEnabled: Boolean
laserSave: Boolean
maintenance: Boolean
testMode: Int
isUpdated: Boolean
isCalibrated: Boolean
mfgDate: DateTime
addedBy: String
inventory: Inventory
hardware: HardwareInfo
calibration: Calibration
locationId: String
interval: Int
preferredGW: Int
status: Status
location: Location
}
type Inventory {
HTP: String
GC: String
PMS: String
Gas: String
AUX: String
LVL: String
sensors: [SensorInfo]
}
type SensorInfo {
_id: String
type: String
name: String
}
type HardwareInfo {
HWVer: String
Ant: String
RTC: String
PWRType: String
LED: Boolean
configVersion: String
firmwareVersion: String
hardwareVersion: String
hardwareType: String
secondaryWiFiSSID: String
}
type Calibration {
Temp: CalObject
Hum: CalObject
Press: CalObject
PMS1: CalObject
PMS25: CalObject
PMS10: CalObject
CO2: CalObject
PPM: CalObject
VCC: CalObject
Count: CalObject
VOC: CalObject
NOx: CalObject
WaterLevel: CalObject
session: CalSession
report: CalReport
}
type CalObject {
A: Float
B: Float
}
type DeviceModel {
_id: Int
name: String
PWRType: String
uplink: [String]
sensors: [String]
telemetry: [String]
}
type ActionResult {
success: Boolean
WiFiSSID: String
WiFiPassword: String
}
input DeviceFilter {
_id: String
model: String
locationId: String
testMode: Boolean
isCalibrated: Boolean
sleepEnabled: Boolean
}
input NewDevice {
id: String!
firmwareVersion: String
hardwareVersion: String
model: Int
HTP: String
PMS: String
Gas: String
GC: String
LED: Boolean
Ant: String
}
input NewDevices {
id: [String]!
firmwareVersion: String
hardwareVersion: String
model: Int
HTP: String
PMS: String
Gas: String
GC: String
LED: Boolean
Ant: String
}
input EditDevice {
id: String!
firmwareVersion: String
LED: Boolean
Ant: String
}
input NewCustomDevice {
id: String!
firmwareVersion: String
hardwareVersion: String
model: Int
HTP: String
PMS: String
GC: String
}
input DeviceInput {
_id: String
model: Int
Sensorcom: Boolean
Narodmon: Boolean
sleepEnabled: Boolean
laserSave: Boolean
maintenance: Boolean
mfgDate: String
testing: Boolean
inventory: InventoryInput
hardware: HardwareInput
}
input InventoryInput {
HTP: String
GC: String
PMS: String
}
input HardwareInput {
HWVer: String
Ant: String
RTC: String
PWRType: String
LED: Boolean
configVersion: Int
firmwareVersion: String
hardwareVersion: String
hardwareType: String
}
input AddCal {
locationId: String!
time: DateTime
reset: Boolean
extAPI: Boolean
metric: CalMetric
value: Float
}
input SendAction {
deviceId: String!
doReboot: Boolean
LEDOn: Boolean
setSecondaryWiFi: Creds
maintenance: Boolean
fwUpgrade: Boolean
rebootFlag: Boolean
OTAFlag: Boolean
immTx: Boolean
preferredGW: Int
interval: Int
}
input Creds {
WiFiSSID: String
WiFiPassword: String
}
"""
Metrics supported as manual calibration targets.
"""
enum CalMetric {
Temp
Hum
}
type Location {
_id: String!
city: String
name: String!
deviceId: String
initDate: DateTime
isPublic: Boolean
isPrivate: Boolean
inactive: Boolean
inactivationDate: DateTime
ownerId: String
elevation: Int
latitude: Float
longitude: Float
Sensorcom: Boolean
Narodmon: Boolean
isOnline: Boolean
status: Status
device: Device
user: User
metricList: [String]
sensorList: [String]
timeSeries(filter: TimeSpan): [SensorData]
timeSeries_export(filter: TimeSpan): [SensorData]
currentValue(filter: TimeSpan): SensorData
sensorvalues_raw(input: TimeSpan): [SensorData]
sensorvalues(input: TimeSpan): [SensorData]
meanvalues_raw(input: TimeSpan): [SensorData]
meanvalues(input: TimeSpan): [SensorData]
mean_last_raw(input: TimeSpan): [SensorData]
mean_last(input: TimeSpan): [SensorData]
mean_city_raw(input: TimeSpan): [SensorData]
mean_city(input: TimeSpan): [SensorData]
telemetry(input: TimeSpan): [Telemetry]
externalWeatherData: SensorData
}
type Status {
_id: String
RSSI: Int
channel: Int
build: String
created: String
ext_ip: String
local_ip: String
isOnline: Boolean
lastOnline: DateTime
maintenance: Boolean
LEDOn: Boolean
start: String
stop: String
uptime: Int
}
"""
Sensor reading row. All metric fields are optional; only those measured by the device are populated.
"""
type SensorData {
deviceId: String
time: DateTime
Temp: Float
Temp1: Float
wTemp: Float
Hum: Float
Press: Float
PMS1: Float
PMS25: Float
PMS10: Float
Count: Float
radRg: Float
CO2: Float
PPM: Float
eCO2: Float
NOx: Float
VOC: Float
Windsp: Float
Windgs: Float
Windir: Float
Rain: Float
WaterLevel: Float
SolRad: Float
Light: Float
AQI: Int
IKAV: Float
}
type Telemetry {
deviceId: String
time: DateTime
VCC: Float
RSSI: Int
Uptime: Int
}
type Marker {
_id: String
name: String
latitude: Float
longitude: Float
text: String
isPublic: Boolean
owned: Boolean
metricList: [String]
value: Float
values: [SensorData]
}
input LocationFilter {
_id: String
_ids: [String]
locationId: String
deviceId: String
city: String
cityId: String
name: String
ownerId: String
isOnline: Boolean
isPublic: Boolean
inactive: Boolean
device: DeviceInput
}
input TimeSpan {
t_from: String
t_to: String
interval_d: Int = 0
interval_h: Int = 0
interval_m: Int = 0
}
input LastFilter {
city: String
cityName: String
cityId: String
interval_d: Int = 0
interval_h: Int = 0
interval_m: Int = 15
}
input MeanFilter {
city: String
cityName: String
cityId: String
t_from: String
t_to: String
interval_d: Int = 0
interval_h: Int = 0
interval_m: Int = 0
}
input MarkerFilter {
city: String
isOnline: Boolean
mapLayer: String
}
input LocInput {
_id: String
}
input PlaceFilter {
latitude: Float
longitude: Float
lang: String = "ru"
}
input NewLocation {
deviceId: String!
name: String!
ownerId: String!
}
input WebLocation {
deviceId: String!
name: String!
isPublic: Boolean
elevation: Int
latitude: Float
longitude: Float
}
input ChgLocation {
_id: String!
name: String
elevation: Int
latitude: Float
longitude: Float
Sensorcom: Boolean
Narodmon: Boolean
}
input inactivateLocation {
_id: String!
}
input LocationInput {
_id: String
deviceId: String
initDate: DateTime
isPublic: Boolean
name: String
ownerId: String
latitude: Float
longitude: Float
elevation: Int
device: DeviceInput
}
type User {
_id: String
email: String!
name: String
locale: String
regDate: DateTime
authSource: String
googleId: String
roles: [String]
picture: String @deprecated(reason: "Use photoURL instead.")
photoURL: String
notificationToken: String
lastReadNews: Int
emailVerified: Boolean
preferredCity: City
APItokens: [APIToken]
widgets: [Widget]
adminProperties: AdminProperties
locations: [Location]
devices: [Device]
}
type AdminProperties {
country: [String]
refDevice: [String]
}
type Me {
name: String
email: String
expiryDate: DateTime
apiRoles: [String]
apiScopes: [String]
}
type AuthResponse {
token: String
name: String
email: String
roles: [String]
_id: String
regDate: String
emailVerified: Boolean
}
type VerifyEmailResponse {
success: Boolean!
message: String
}
type APIToken {
_id: String
tokenName: String
token: String
issDate: DateTime
expDate: DateTime
}
type RevokeResponse {
success: Boolean
}
input AuthInput {
accessToken: String!
}
input LocalAuthInput {
email: String!
password: String!
}
input RegisterInput {
email: String!
password: String!
name: String
}
input UserInput {
_id: String
email: String
name: String
token: String
locale: String
lastReadNews: Int
}
input RefDevice {
_id: String
}
input NewTokenInput {
tokenName: String!
validityDays: Int = 180
}
type Query {
location(filter: LocationFilter): Location
locations(filter: LocationFilter): [Location]
cityList(langId: String, countryCode: String): [City]
getMarkers(filter: MarkerFilter): [Marker]
myLocation: Location
myLocations: [Location]
cityAverage(filter: MeanFilter): [SensorData]
cityAverageLast(filter: LastFilter): SensorData
getPlace(filter: PlaceFilter): City
me: User
widgetList(input: UserInput): [Widget]
deviceList: [Location]
devices(filter: DeviceFilter): [Device]
getUncalibratedDevices: [Device]
checkSetupSuccess(deviceId: String): Device
listCalibrationSessions: [CalSession]
users(filter: UserInput): [User]
}
type Mutation {
authGoogle(input: AuthInput!): AuthResponse
authGoogleApp(input: AuthInput!): AuthResponse
authGoogleWeb(input: AuthInput!): AuthResponse
loginLocal(input: LocalAuthInput!): AuthResponse
register(input: RegisterInput!): AuthResponse
verifyEmail(token: String!): VerifyEmailResponse
resendVerification(email: String!): Boolean
addUser(input: UserInput): User
updateUser(input: UserInput): User
setLastReadNews(_id: String): User
updateNotificationToken(token: String!): User
generateAPIToken(input: NewTokenInput): APIToken
revokeAPIToken: RevokeResponse
initLocation(input: NewLocation): Location
addLocation(input: LocationInput): Location
addWebLocation(input: WebLocation): Location
changeLocation(input: ChgLocation): Location
changeWebLocation(input: ChgLocation): Location
archiveLocation(input: inactivateLocation): Location
initDevice(input: NewDevice): Device
initDevices(input: NewDevices): [Device]
editDevice(input: EditDevice): Device
addCustomDevice(input: NewCustomDevice): Device
deviceAction(input: SendAction): ActionResult
setCalibration(input: AddCal): Device
startCalibration(input: CalStartInput): CalSession
stopCalibration(input: CalStopInput): CalSession
setRefDevice(input: RefDevice): User
addWidget(input: AddWidgetInput): [Widget]
moveWidget(input: MoveWidgetInput): [Widget]
removeWidget(input: RemoveWidgetInput): [Widget]
}
type Subscription {
onLocationAdded: Location
onLocationChanged(input: LocInput): Location
}
"""
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
"""
scalar String
"""
A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.
"""
type __Schema {
description: String
"""
A list of all types supported by this server.
"""
types: [__Type!]!
"""
The type that query operations will be rooted at.
"""
queryType: __Type!
"""
If this server supports mutation, the type that mutation operations will be rooted at.
"""
mutationType: __Type
"""
If this server support subscription, the type that subscription operations will be rooted at.
"""
subscriptionType: __Type
"""
A list of all directives supported by this server.
"""
directives: [__Directive!]!
}
"""
The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.
Depending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name, description and optional `specifiedByURL`, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.
"""
type __Type {
kind: __TypeKind!
name: String
description: String
specifiedByURL: String
fields(includeDeprecated: Boolean = false): [__Field!]
interfaces: [__Type!]
possibleTypes: [__Type!]
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
inputFields(includeDeprecated: Boolean = false): [__InputValue!]
ofType: __Type
isOneOf: Boolean
}
"""
An enum describing what kind of type a given `__Type` is.
"""
enum __TypeKind {
"""
Indicates this type is a scalar.
"""
SCALAR
"""
Indicates this type is an object. `fields` and `interfaces` are valid fields.
"""
OBJECT
"""
Indicates this type is an interface. `fields`, `interfaces`, and `possibleTypes` are valid fields.
"""
INTERFACE
"""
Indicates this type is a union. `possibleTypes` is a valid field.
"""
UNION
"""
Indicates this type is an enum. `enumValues` is a valid field.
"""
ENUM
"""
Indicates this type is an input object. `inputFields` is a valid field.
"""
INPUT_OBJECT
"""
Indicates this type is a list. `ofType` is a valid field.
"""
LIST
"""
Indicates this type is a non-null. `ofType` is a valid field.
"""
NON_NULL
}
"""
Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.
"""
type __Field {
name: String!
description: String
args(includeDeprecated: Boolean = false): [__InputValue!]!
type: __Type!
isDeprecated: Boolean!
deprecationReason: String
}
"""
Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.
"""
type __InputValue {
name: String!
description: String
type: __Type!
"""
A GraphQL-formatted string representing the default value for this input value.
"""
defaultValue: String
isDeprecated: Boolean!
deprecationReason: String
}
"""
One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.
"""
type __EnumValue {
name: String!
description: String
isDeprecated: Boolean!
deprecationReason: String
}
"""
A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
In some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.
"""
type __Directive {
name: String!
description: String
isRepeatable: Boolean!
locations: [__DirectiveLocation!]!
args(includeDeprecated: Boolean = false): [__InputValue!]!
}
"""
A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.
"""
enum __DirectiveLocation {
"""
Location adjacent to a query operation.
"""
QUERY
"""
Location adjacent to a mutation operation.
"""
MUTATION
"""
Location adjacent to a subscription operation.
"""
SUBSCRIPTION
"""
Location adjacent to a field.
"""
FIELD
"""
Location adjacent to a fragment definition.
"""
FRAGMENT_DEFINITION
"""
Location adjacent to a fragment spread.
"""
FRAGMENT_SPREAD
"""
Location adjacent to an inline fragment.
"""
INLINE_FRAGMENT
"""
Location adjacent to a variable definition.
"""
VARIABLE_DEFINITION
"""
Location adjacent to a schema definition.
"""
SCHEMA
"""
Location adjacent to a scalar definition.
"""
SCALAR
"""
Location adjacent to an object type definition.
"""
OBJECT
"""
Location adjacent to a field definition.
"""
FIELD_DEFINITION
"""
Location adjacent to an argument definition.
"""
ARGUMENT_DEFINITION
"""
Location adjacent to an interface definition.
"""
INTERFACE
"""
Location adjacent to a union definition.
"""
UNION
"""
Location adjacent to an enum definition.
"""
ENUM
"""
Location adjacent to an enum value definition.
"""
ENUM_VALUE
"""
Location adjacent to an input object type definition.
"""
INPUT_OBJECT
"""
Location adjacent to an input object field definition.
"""
INPUT_FIELD_DEFINITION
}
directive @isAuthenticated on OBJECT | FIELD_DEFINITION
directive @hasRole(roles: [Role]) on OBJECT | FIELD_DEFINITION
directive @hasScope(scopes: [String]) on OBJECT | FIELD_DEFINITION
"""
Directs the executor to include this field or fragment only when the `if` argument is true.
"""
directive @include("Included when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
"""
Directs the executor to skip this field or fragment when the `if` argument is true.
"""
directive @skip("Skipped when true." if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
"""
Marks an element of a GraphQL schema as no longer supported.
"""
directive @deprecated("Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified by [CommonMark](https://commonmark.org/)." reason: String = "No longer supported") on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE
"""
Exposes a URL that specifies the behavior of this scalar.
"""
directive @specifiedBy("The URL that specifies the behavior of this scalar." url: String!) on SCALAR
"""
Indicates exactly one field must be supplied and this field must not be `null`.
"""
directive @oneOf on INPUT_OBJECT
schema {
query: Query
mutation: Mutation
subscription: Subscription
}