Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Note

GraphQL API v1 is going to be deprecated in 2024Q3. If you plan to use GraphQL API, please, refer to the GraphQL Occupancy API V2

Table of Contents

GraphQL Occupancy API offers similar functionality to REST Occupancy API, however, there are additional benefits to using GraphQL.

You can select the fields you want to receive from the API. By requesting only the required fields from the API you can decrease traffic and consequently increase load speed.

Additionally, GraphQL Occupancy API supports subscriptions, which allows you to receive real-time occupancy updates.

Authorization

In order to authorize with this API, you need to add the following header to your request:

Key

Value

Authorization

<your token>

Your token can be obtained from the Company Info section of the Nwave’s console.

Note

You are able to call API not more frequent, than 300 times per 5 minutes interval with use of the same token. If amount of requests exceeds the limit, API reponds with error until the end of 5 minutes interval.

GraphQL Schema

The following GraphQL schema describes data types and operations that can be performed.

File:

View filenameexpandtitle
Expand
titleschema.graphql
Code Block
schema
Code Block
languagegraphql
language
schema.graphql
graphql
type GroupOccupancy @aws_api_key
@aws_lambda {
	id: ID!
	zoneId: Int
query	levelId: QueryInt
	name: String!
	groupType: String!
mutation	customId: MutationString
	location: Location
	positionsOccupancy: [PositionOccupancy]
subscription	summary: SubscriptionOccupancySummary
}

enuminput OccupancyStatusGroupOccupancyInput {
	id: ID!
	zoneId: Int
Occupied	levelId: Int
	name: String!
	groupType: Free
}

enum SubscriptionGranularity {
    Position
    Level
    Group
    ZoneString!
	customId: String
	location: LocationInput!
	positionsOccupancy: [PositionOccupancyInput!]!
	summary: OccupancySummaryInput!
}

type LocationLevelOccupancy @aws_api_key
@aws_lambda {
	id: Int
	name: String
lat	zoneId: FloatInt!
	floorNumber: Int
  lon	summary: Float!OccupancySummary
}

input LocationInputLevelOccupancyInput {
	id: Int
	zoneId: Int!
lat	floorNumber: Float!Int
	name: String
  lon	summary: FloatOccupancySummaryInput!
}

type OccupancySummaryLocation  @aws_api_key
@aws_lambda {
	lat:    totalFloat!
	lon: IntFloat!
}

input LocationInput {
occupied	lat: IntFloat!
    available	lon: IntFloat!
}

enum OccupancyStatus {
undefined: Int!	Occupied
	Free
}

inputtype OccupancySummaryInput {
    OccupancySummary @aws_api_key
@aws_lambda {
	total: Int!
    	occupied: Int!
	available: Int!
	undefined: Int!
}

availableinput OccupancySummaryInput {
	total: Int!
	occupied: Int!
	available: Int!
	undefined: Int!
}

type PositionOccupancy  @aws_api_key
@aws_lambda {
    	id: IntID!
    	customId: String
    	groupId: Int
    	occupancyStatus: OccupancyStatus
    	statusChangeTime: AWSDateTime
    	location: Location!
	labels: [String]
}

input PositionOccupancyInput {
    	id: IntID!
    	customId: String
    	groupId: Int!
    	occupancyStatus: OccupancyStatus!
	statusChangeTime: AWSDateTime!
	location: LocationInput!
statusChangeTime	labels: AWSDateTime![String]
}

union RtaUpdateObject location:= LocationInput!ZoneOccupancy }| LevelOccupancy type| GroupOccupancy  @aws_api_key @aws_lambda {| PositionOccupancy 

interface SubscriptionArea {
	id: IntID!
	location: Location
	radius: Int
	zoneId: [Int]
    	levelId: [Int]
	floorNumber: [Int]
	groupId: [Int]
name	labels: [String!]
	granularity:    groupTypeSubscriptionGranularity!
	expiresOn: StringAWSDateTime!
}

type SubscriptionAreaNoUpdates implements customId: String
    SubscriptionArea @aws_api_key
@aws_lambda {
	id: ID!
	location: Location
	radius: Int
	zoneId: [Int]
positionsOccupancy	levelId: [PositionOccupancyInt]
	floorNumber: [Int]
	groupId: [Int]
summary	labels: OccupancySummary
}

input GroupOccupancyInput {
    id: Int!
    zoneId: Int
    levelId: Int
    name: String!
    groupType: String!
    customId: String
    location: LocationInput!
    positionsOccupancy: [PositionOccupancyInput!]!
    summary: OccupancySummaryInput!
}

type LevelOccupancy [String]
	granularity: SubscriptionGranularity!
	expiresOn: AWSDateTime!
}

type SubscriptionAreaWithUpdates implements SubscriptionArea @aws_api_key
@aws_lambda {
	id: ID!
	location: Location
	radius: Int
	zoneId: [Int]
	levelId: [Int]
	floorNumber: [Int]
	groupId: [Int]
	labels: [String]
	granularity: SubscriptionGranularity!
	expiresOn: AWSDateTime!
	updates: [RtaUpdateObject]
	updateTime: AWSDateTime
}

enum SubscriptionGranularity {
	Position
	Level
	Group
	Zone
}

type ZoneOccupancy @aws_api_key
@aws_lambda {
    	id: Int
    ID!
	name: String
    zoneId: Int!
    floorNumber	projectId: Int
    	summary: OccupancySummary
}

input LevelOccupancyInputZoneOccupancyInput {
	id: ID!
	name: String!
id	projectId: Int
    zoneId	summary: IntOccupancySummaryInput!
}

type Mutation floorNumber: Int
    name: String
    summary: OccupancySummaryInput!
}

type ZoneOccupancy  {
	createSubscriptionArea(
		lat: Float,
		lon: Float,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity
	): SubscriptionAreaNoUpdates
		@aws_api_key
@aws_lambda
{
    id: Int!
    name: String!
    projectId: Int
    summary: OccupancySummary
}

input ZoneOccupancyInput {
    id: Int!
    name: String!
    projectId: Int
    summary: OccupancySummaryInput!
}

union RtaUpdateObject = ZoneOccupancy | LevelOccupancy | GroupOccupancy | PositionOccupancy

interface SubscriptionArea {
    id: Int!
    location: Location
    radius: Int
    zoneId: [Int]
    levelId: [Int]
    floorNumber: [Int]
    groupId: [Int]
    labels: [String]
    granularity: SubscriptionGranularity!
    expiresOn: AWSDateTime!
}

type SubscriptionAreaNoUpdates implements SubscriptionArea @aws_api_key @aws_lambda {
    id: Int!
    location: Location
    radius: Int
    zoneId: [Int]
    levelId: [Int]
    floorNumber: [Int]
    groupId: [Int]
    labels: [String]
    granularity: SubscriptionGranularity!
    expiresOn: AWSDateTime!
}

type SubscriptionAreaWithUpdates implements SubscriptionArea @aws_api_key @aws_lambda {
    id: Int!
    location: Location
    radius: Int
    zoneId: [Int]
    levelId: [Int]
    floorNumber: [Int]
    groupId: [Int]
    labels: [String]
    granularity: SubscriptionGranularity!
    expiresOn: AWSDateTime!
    updates: [RtaUpdateObject]
    updateTime: AWSDateTime
	updateSubscriptionArea(
		id: ID!,
		lat: Float,
		lon: Float,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity
	): SubscriptionAreaNoUpdates
		@aws_api_key
@aws_lambda
	updatePositionOccupancy(positionId: Int!, occupancyStatus: OccupancyStatus!, timestamp: String!): PositionOccupancy
		@aws_api_key
	pushPositionUpdates(
		id: ID!,
		location: LocationInput,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity!,
		expiresOn: AWSDateTime!,
		updates: [PositionOccupancyInput!]!,
		updateTime: String!
	): SubscriptionAreaWithUpdates
		@aws_api_key
	pushGroupUpdates(
		id: ID!,
		location: LocationInput,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity!,
		expiresOn: AWSDateTime!,
		updates: [GroupOccupancyInput!]!,
		updateTime: String!
	): SubscriptionAreaWithUpdates
		@aws_api_key
	pushLevelUpdates(
		id: ID!,
		location: LocationInput,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity!,
		expiresOn: AWSDateTime!,
		updates: [LevelOccupancyInput!]!,
		updateTime: String!
	): SubscriptionAreaWithUpdates
		@aws_api_key
	pushZoneUpdates(
		id: ID!,
		location: LocationInput,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity!,
		expiresOn: AWSDateTime!,
		updates: [ZoneOccupancyInput!]!,
		updateTime: String!
	): SubscriptionAreaWithUpdates
		@aws_api_key
}

type Query {
    	groupOccupancy(id: IntID!): GroupOccupancy
		@aws_api_key
@aws_lambda
    	findGroupOccupancies(
        		ids: [Int]
        ,
		lat: Float
        ,
		lon: Float
        ,
		radius: Int
        ,
		levelId: [Int!],
		labels:        [String!],
		floorNumber: [Int!]
        ,
		zoneId: [Int!]
        ,
		projectId: Int
        ,
		groupCustomId: String
        ,
		limit: Int = 50
        ,
		offset: Int
    ) : [	): [GroupOccupancy]
		@aws_api_key
@aws_lambda
    	findPositionOccupancies(
        		ids: [Int]
        ,
		lat: Float
        ,
		lon: Float
        ,
		radius: Int
        ,
		groupId: [Int!]
        ,
		levelId: [Int!],
		labels:        [String!],
		floorNumber: [Int!]
        ,
		zoneId: [Int!]
        ,
		projectId: Int
        ,
		groupCustomId: String
        ,
		limit: Int = 50
        ,
		offset: Int
    	) : [PositionOccupancy]
		@aws_api_key
@aws_lambda
}

type MutationSubscription {
    createSubscriptionArea(
        lat: Float,
        lon: Float,
        radius: Int,
        zoneId: [Int],
        levelId: [Int],
        floorNumber: [Int],
        groupId: [Int],
        labels: [String],
        granularity: SubscriptionGranularity
    ): SubscriptionAreaNoUpdates @aws_api_key @aws_lambda
    updateSubscriptionArea(
        id: Int!,
        lat: Float,
        lon: Float,
        radius: Int,
        zoneId: [Int],
        levelId: [Int],
        floorNumber: [Int],
        groupId: [Int],
        labels: [String],
        granularity: SubscriptionGranularity
    ): SubscriptionAreaNoUpdates @aws_api_key @aws_lambda
    updatePositionOccupancy(
        positionId: Int!,
        occupancyStatus: OccupancyStatus!,
        timestamp: String!
    ): PositionOccupancy @aws_api_key
    pushPositionUpdates(
        id: Int!,
        location: LocationInput,
        radius: Int,
        zoneId: [Int],
        levelId: [Int],
        floorNumber: [Int],
        groupId: [Int],
        labels: [String],
        granularity: SubscriptionGranularity!,
        expiresOn: AWSDateTime!,
        updates: [PositionOccupancyInput!]!,
        updateTime: String!
    ): SubscriptionAreaWithUpdates @aws_api_key
    pushGroupUpdates(
        id: Int!,
        location: LocationInput,
        radius: Int,
        zoneId: [Int],
        levelId: [Int],
        floorNumber: [Int],
        groupId: [Int],
        labels: [String],
        granularity: SubscriptionGranularity!,
        expiresOn: AWSDateTime!,
        updates: [GroupOccupancyInput!]!,
        updateTime: String!
    ): SubscriptionAreaWithUpdates @aws_api_key
    pushLevelUpdates(
        id: Int!,
        location: LocationInput,
        radius: Int,
        zoneId: [Int],
        levelId: [Int],
        floorNumber: [Int],
        groupId: [Int],
        labels: [String],
        granularity: SubscriptionGranularity!,
        expiresOn: AWSDateTime!,
        updates: [LevelOccupancyInput!]!,
        updateTime: String!
    ): SubscriptionAreaWithUpdates @aws_api_key
    pushZoneUpdates(
        id: Int!,
        location: LocationInput,
        radius: Int,
        zoneId: [Int],
        levelId: [Int],
        floorNumber: [Int],
        groupId: [Int],
        labels: [String],
        granularity: SubscriptionGranularity!,
        expiresOn: AWSDateTime!,
        updates: [ZoneOccupancyInput!]!,
        updateTime: String!
    ): SubscriptionAreaWithUpdates @aws_api_key
}

type Subscription {
    onSubscriptionAreaUpdates(id: Int!): SubscriptionAreaWithUpdates @aws_api_key @aws_lambda @aws_subscribe(mutations : ["pushPositionUpdates", "pushGroupUpdates", "pushLevelUpdates", "pushZoneUpdates"])
}

Subscription Areas

A subscription area is an object that has two main functions:

  1. Filtering of the incoming position updates

  2. Defining the format of updates that is received by subscribers

There are two types defined in the GraphQL schema for Subscription Areas:

SubscriptionAreaNoUpdates - this type is returned when you create or update a Subscription Area. It does not have ‘updates’ & ‘updateTime’ fields as updates are only returned to active subscriptions.

Info

Subscription areas 5 minutes after creation. Any update of a subscription area, including an empty one, will extend the expiration time by 5 minutes from the time of update.

SubscriptionAreaWithUpdates - this type is returned to subscribers and as the name suggests it contains the ‘updates’ & ‘updateTime’ fields.

Subscription Area Filters

Subscription Areas filter the incoming updates and only notify the subscribers if the incoming position update matches all of the filters. Subscription Area filters can also be split into 2 categories:

  1. Hierarchical Filters: zoneId, groupId, levelId, floorNumber, labels

  2. Geospatial Filters: lat, lon, radius

Info

A valid subscription area must have at least one hierarchical filter and/or all of the geospatial filters.

A match is when all position attributes are a subset (⊆) of the Subscription Area filters.

Subscription Area filter with null value matches everything.

The following example is a valid match between Subscription Area and Position Update.

Position

  1. zoneId: 1

  2. groupId: 2

  3. levelId: 3

  4. floorNumber: 4

  5. labels: ['EV', ‘Disabled’]

  6. lat: 0.0

  7. lon: 0.0

Subscription Area

  1. zoneId: [1, 2, 3]

  2. groupId: [1, 2, 3]

  3. levelId: [3]

  4. floorNumber: null

  5. lables: ['EV', ‘Disabled’, ‘VIP’]

  6. lat: 0.0

  7. lon: 0.0

  8. radius: 100

Note

Geospatial filters create a circular search area on the map, and there can be cases when a group of devices partially falls into the search area. (e.g. Half a group is within the search area and half is outside of the search area).

Updates for positions that do not fall into the search area would still notify the subscribers.

Subscription Area Updates

The updates field of a Subscription Area can contain a list of 4 different types. All types within the updates list are the same. The type you will receive in the updates field depends on the granularity you choose.

Granularity

Updates Type

Zone

ZoneOccupancy

Level

LevelOccupancy

Group

GroupOccupancy

Position

PositionOccupancy

Info

Updates field will always contain only the object that has changed and therfore the list should always have a length of 1.

Object & Field Descriptions

SubscirptionArea

  • id - subscription area id

  • location - center coordinates of the search area

  • radius - radius from the center in meeters that creates the search area

  • zoneId - list of zone ids to match

  • levelId - list of level ids to match

  • floorNumber - list of floor numbers to match

  • groupId - list of group ids to match

  • labels - list of labels to match

  • granularity - defines the updates type

  • expiresOn - timestamp of subscription area expiration

  • udpates - occupancy updates for a subscription area

  • updateTime - timestamp of the occupancy update

ZoneOccupancy

  • id - zone id

  • name - zone name

  • projectId - project id

  • summary - summary of occupancies in the Zone

LevelOccupancy

  • id - level id

  • name - level name

  • zoneId - zone id

  • floorNumber - floor number of a level

  • summary - summary of occupancies on a Level

GroupOccupancy

  • id - group id

  • zoneId - zone id

  • levelId - level id

  • name - group name

  • groupType - group type e.g. marked_bay

  • customId - user defined group id

  • location - сenter coordinates of a group

  • positionOccupancy - list of PositionOccupancy objects for a group

  • summary - summary of occupancies in the Group

PositionOccupancy

  • id - position id

  • customId - custom id

  • groupId - group id

  • occupancyStatus - ‘occupied’, ‘free’ or null

  • statusChangeTime - timestamp of last occupancyStatus change

  • location: coordinates of a position

Info

The summary object should be used to display availability for all parking group types as it handles unmarked bay occupancies

Operations

The following operations can be performed using either Postman or curl command except for subscription operations.

groupOccupancy

This query will return the occupancy of a single group.

Query

Code Block
languagegraphql
query MyQuery {
  groupOccupancy(id: 123) {
    id
    customId
    name
    location {
      lat
      lon
    }
    positionsOccupancy {
      customId
      id
      groupId
      location {
        lat
        lon
      }
      occupancyStatus
      statusChangeTime
    }
  }
}

Response

Code Block
languagejson
{ "data": { "groupOccupancy": {
	onSubscriptionAreaUpdates(id: ID!): SubscriptionAreaWithUpdates
		@aws_api_key
@aws_lambda
@aws_subscribe(mutations: ["pushPositionUpdates","pushGroupUpdates","pushLevelUpdates","pushZoneUpdates"])
}

# @api_key (admin) auth and @aws_lambda (user) auth are required for all types apart from:
##   updatePositionOccupancy
##   pushPositionUpdates
##   pushGroupUpdates
##   pushLevelUpdates
##   pushZoneUpdates
## These are for internal subscription notification and should have exclusive admin access
schema {
	query: Query
	mutation: Mutation
	subscription: Subscription
}

Subscription Areas

A subscription area is an object that has two main functions:

  1. Filtering of the incoming position updates

  2. Defining the format of updates that is received by subscribers

There are two types defined in the GraphQL schema for Subscription Areas:

SubscriptionAreaNoUpdates - this type is returned when you create or update a Subscription Area. It does not have ‘updates’ & ‘updateTime’ fields as updates are only returned to active subscriptions.

Info

Subscription areas expiry 5 minutes after creation. Any update of a subscription area, including an empty one, will extend the expiration time by 5 minutes from the time of update.

SubscriptionAreaWithUpdates - this type is returned to subscribers and as the name suggests it contains the ‘updates’ & ‘updateTime’ fields.

Subscription Area Filters

Subscription Areas filter the incoming updates and only notify the subscribers if the incoming position update matches all of the filters. Subscription Area filters can also be split into 2 categories:

  1. Hierarchical Filters: zoneId, groupId, levelId, floorNumber, labels

  2. Geospatial Filters: lat, lon, radius

Info

A valid subscription area must have at least one hierarchical filter and/or all of the geospatial filters.

A match is when all position attributes are a subset (⊆) of the Subscription Area filters and it implies that a given position is inside a Subscription Area.

Subscription Area filter with null value matches everything.

The following example is a valid match between Subscription Area and Position Update.

Position

  1. zoneId: 1

  2. groupId: 2

  3. levelId: 3

  4. floorNumber: 4

  5. labels: ['EV', ‘Disabled’]

  6. lat: 0.0

  7. lon: 0.0

Subscription Area

  1. zoneId: [1, 2, 3]

  2. groupId: [1, 2, 3]

  3. levelId: [3]

  4. floorNumber: null

  5. lables: ['EV', ‘Disabled’, ‘VIP’]

  6. lat: 0.0

  7. lon: 0.0

  8. radius: 100

Note

Geospatial filters create a circular search area on the map, and there can be cases when a group of devices partially falls into the search area. (e.g. Half a group is within the search area and half is outside of the search area).

Updates for positions that do not fall into the search area would still notify the subscribers.

Subscription Area Updates

The updates field of a Subscription Area can contain a list of 4 different types. All types within the updates list are the same. The type you will receive in the updates field depends on the granularity you choose.

Granularity

Updates Type

Zone

ZoneOccupancy

Level

LevelOccupancy

Group

GroupOccupancy

Position

PositionOccupancy

Info

Updates field will always contain only the object that has changed and therfore the list should always have a length of 1.

Object & Field Descriptions

SubscirptionArea

  • id - subscription area id

  • location - center coordinates of the search area

  • radius - radius from the center in meeters that creates the search area

  • zoneId - list of zone ids to match

  • levelId - list of level ids to match

  • floorNumber - list of floor numbers to match

  • groupId - list of group ids to match

  • labels - list of labels to match

  • granularity - defines the updates type

  • expiresOn - timestamp of subscription area expiration

  • udpates - occupancy updates for a subscription area

  • updateTime - timestamp of the occupancy update

ZoneOccupancy

  • id - zone id

  • name - zone name

  • projectId - project id

  • summary - summary of occupancies in the Zone

LevelOccupancy

  • id - level id

  • name - level name

  • zoneId - zone id

  • floorNumber - floor number of a level

  • summary - summary of occupancies on a Level

GroupOccupancy

  • id - group id

  • zoneId - zone id

  • levelId - level id

  • name - group name

  • groupType - group type e.g. marked_bay

  • customId - user defined group id

  • location - сenter coordinates of a group

  • positionOccupancy - list of PositionOccupancy objects for a group

  • summary - summary of occupancies in the Group

PositionOccupancy

  • id - position id

  • customId - custom id

  • groupId - group id

  • occupancyStatus - ‘occupied’, ‘free’ or null

  • statusChangeTime - timestamp of last occupancyStatus change

  • location: coordinates of a position

Info

The summary object should be used to display availability for all parking group types as it handles unmarked bay occupancies

Operations

The following operations can be performed using either Postman or curl command except for subscription operations.

groupOccupancy

This query will return the occupancy of a single group.

Query

Code Block
languagegraphql
query MyQuery {
  groupOccupancy(id: 123) {
    id
    customId
    name
    location {
      lat
      lon
    }
    positionsOccupancy {
      customId
      id
      groupId
      labels
      location {
        lat
        lon
      }
      occupancyStatus
      statusChangeTime
    }
  }
}

Response

Code Block
languagejson
{
  "data": {
    "groupOccupancy": {
      "id": 3544,
      "customId": null,
      "name": "Foo",
      "location": {
        "lat": 51.493601937687224,
        "lon": -0.12852029611716095
      },
      "positionsOccupancy": [
        {
          "customId": "",
          "id": 1,
          "groupId": 123,
          "labels": null,
          "location": {
            "lat": 51.49360068522545,
            "lon": -0.1286061268139623
          },
          "occupancyStatus": "Free",
          "statusChangeTime": "2021-01-27T19:22:47.548+00:00"
        },
        {
          "customId": "",
          "id": 35442,
          "customIdgroupId": null123,
          "namelabels": "Foo"null,
          "location": {
            "lat": 51.493601937687224,
            "lon": -0.1285202961171609512852029611716098
          },
          "positionsOccupancyoccupancyStatus": ["Occupoed",
        {  "statusChangeTime": "2021-01-27T18:56:53.502+00:00"
       "customId": "", }
      ]
   "id": 1, }
  }
}

findGroupOccupancies

This query will return a list of group occupancies.

Query

Code Block
languagegraphql
query MyQuery {
    "groupId": 123,
findGroupOccupancies(ids: [1234]) {
    id
    "location": {
      lat
     "lat": 51.49360068522545, lon
    }
    summary {
   "lon": -0.1286061268139623  available
      occupied
 },     total
     "occupancyStatus": "Free", undefined
    }
  }
}

 

Response

Code Block
languagejson
{
  "statusChangeTimedata": "2021-01-27T19:22:47.548+00:00"{
        },"findGroupOccupancies": [
        {
 
        "customIdid": ""1234,
          "idlocation": 2,{
          "groupIdlat": 12350.780416909504915,
          "location": {"lon": -1.0914407438684124
        },
        "latsummary": 51.493601937687224,
 {
          "lonavailable": -0.1285202961171609834,
          "occupied": }13,
          "occupancyStatustotal": "Occupoed"47,
          "statusChangeTimeundefined": "2021-01-27T18:56:53.502+00:00"0
        }
      ]}
    }]
  }
}
findGroupOccupancies

findPositionOccupancies

This query will return a list of group position occupancies.

Query

Code Block
languagegraphql
query MyQuery {
  findGroupOccupanciesfindPositionOccupancies(ids: [12341]) {
    id
    location {labels
      lat
      lon
    }location {
    summary { lat
     available lon
    }
occupied    occupancyStatus
  total  statusChangeTime
    undefinedgroupId
    }customId
  }
}

 

Response

Code Block
languagejson
{
  "data": {
    "findGroupOccupanciesfindPositionOccupancies": [
      {
        "id": 123412345,
        "labels":["EV", "VIP"],
        "location": {
          "lat": 5051.78041690950491549360068522545,
          "lon": -10.09144074386841241286061268139623
        },
        "summaryoccupancyStatus": {"Free",
        "statusChangeTime": "2021-01-27T19:22:47.548+00:00",
        "availablegroupId": 34123,
 
        "occupiedcustomId": 13,""
      }
   "total": 47, ]
  }
}

createSubscriptionArea

This mutation will create a new subscription area.

Subscription Area Expiration

By default, subscription areas expire 5 minutes after creation. Once a subscription area is expired, it cannot be extended and subscribers will stop receiving updates.

Mutation

Code Block
languagegraphql
mutation MyMutation {
  createSubscriptionArea(
 "undefined": 0  granularity: Group, 
    } lat: 51.493930, 
   } lon: -0.129030, 
 ]   }
}

findPositionOccupancies

This query will return a list of position occupancies.

Query

Code Block
languagegraphql
query MyQuery {
  findPositionOccupancies(ids: [1]) {
    id
    location {
 radius: 100,
    labels: ["EV"]
  ) {
    expiresOn
    granularity
    latid
    location {
lon     } lat
   occupancyStatus   lon
 statusChangeTime   }
 groupId   radius
 customId  }
}
}

 

Response

{
Code Block
languagejson
{
  "data": {
    "datacreateSubscriptionArea": {
      "findPositionOccupanciesexpiresOn": ["2021-01-28T23:20:06.232+00:00",
      {
 "granularity": "Group",
      "id": 123451,
        "location": {
          "lat": 51.4936006852254549393,
 
        "lon": -0.1286061268139623
 12903
      },
 
      "occupancyStatus": "Free",
        "statusChangeTime": "2021-01-27T19:22:47.548+00:00","radius": 100
    }
   "groupId": 123,
        "customId": ""
}
}

onSubscriptionAreaUpdates

This subscription will subscribe to occupancy updates inside an area.

Selected updates object type must correspond to the granularity of the created search area:

  1. granularity: Position → updates { … on PositionOccupancy }

  2. granularity: Group → updates { … on GroupOccupancy }

If you are unsure of the granularity for your subscription area, you can specify both types inside the updates.

Subscription

Code Block
languagegraphql
subscription MySubscription {
  onSubscriptionAreaUpdates(id: 1) {
    id
}
    ]   }
}

createSubscriptionArea

This mutation will create a new subscription area.

Subscription Area Expiration

By default, subscription areas expire 5 minutes after creation. Once a subscription area is expired, it cannot be extended and subscribers will stop receiving updates.

Mutation

Code Block
languagegraphql
mutation MyMutation {
  createSubscriptionArea( expiresOn
    granularity
    location granularity:{
Group,      lat:
51.493930,      lon: -0.129030, 
    }
    radius: 100
    updateTime
    )updates {
      ... on expiresOnGroupOccupancy {
   granularity     id
        name
        customId
        location {
          lat
          lon
   lon     }
    radius   } }

 

Response

Code Block
languagejson
positionsOccupancy {
  "data": {     "createSubscriptionArea": { customId
     "expiresOn": "2021-01-28T23:20:06.232+00:00",    groupId
  "granularity": "Group",       "id": 1,
          "location": {
           "lat": 51.49393, lat
            "lon": -0.12903
          },
      "radius": 100   occupancyStatus
 }
  }
}

onSubscriptionAreaUpdates

This subscription will subscribe to occupancy updates inside an area.

Selected updates object type must correspond to the granularity of the created search area:

  1. granularity: Position → updates { … on PositionOccupancy }

  2. granularity: Group → updates { … on GroupOccupancy }

If you are unsure of the granularity for your subscription area, you can specify both types inside the updates.

Subscription

Code Block
languagegraphql
subscription MySubscription {
  onSubscriptionAreaUpdates(id: 1) {
    id         statusChangeTime
          labels
     expiresOn   }
 granularity     location { summary {
    lat      undefined
lon     }     radiustotal
    updateTime     updates {occupied
      ... on GroupOccupancy { available
       id }
      }
name    }
  }
 customId}

 

Update

Code Block
languagejson
{
  "data": {
    location"onSubscriptionAreaUpdates": {
      "id": 1,
  lat    "expiresOn": "2021-01-28T23:20:06.232+00:00",
     lon "granularity": "Group",
      }"location": {
       positionsOccupancy {
"lat": 51.49393,
         customId"lon": -0.12903
      },
   groupId   "radius": 1000,
      id
"updateTime": "2021-01-28T23:17:38.400+00:00",
         location {"updates": [
        {
    lat      "id": 123,
     lon     "name": "Foo",
    }      "customId": null,
   occupancyStatus       "location": {
  statusChangeTime         }   "lat": 51.493601937687224,
     summary {      "lon": -0.12852029611716095
   undefined       },
   total       "positionsOccupancy": [
  occupied          {
available         }     "customId": "",
}     }   } }

 

Update

Code Block
languagejson
{     "datagroupId": 123,
{      "onSubscriptionAreaUpdates": {       "id": 1,
      "expiresOn": "2021-01-28T23:20:06.232+00:00",       "granularitylocation": "Group",{
      "location": {         "lat": 51.4939349360068522545,
                "lon": -0.129031286061268139623
              },
               }"occupancyStatus": "Occupied",
      "radius": 1000,       "updateTimestatusChangeTime": "2021-01-28T23:17:38.400+00:00",
              "updateslabels": [ null
            }
          ],
          "summary": {
            "idundefined": 1230,
            "nametotal": "Foo"1,
            "customIdoccupied": null1,
            "available": 0
   "location": {      }
      "lat": 51.493601937687224, }
      ]
    "lon": -0.12852029611716095}
  }
}

updateSubscriptionArea

This mutation will update an existing subscription area.

Info

All subscription area updates will extend expiration by 5 minutes from the current time.

You can also send empty mutation to only update the expiration.

Mutation

Code Block
languagegraphql
mutation MyMutation {
  updateSubscriptionArea(
 },    id: 1, 
    "positionsOccupancy"granularity: [Position, 
    radius: 500
  ) {
 {   expiresOn
    id
    granularity
 "customId": "",  location {
      lat
    "groupId": 123, lon
    }
    radius
  }
"id": 1,
 }

 

Code Block
languagegraphql
mutation ExtendSubscription {
  updateSubscriptionArea(
    id: 1, 
  "location":) {
    expiresOn
    id
  }
   "lat": 51.49360068522545,}

Response

Code Block
languagejson
{
  "data": {
    "updateSubscriptionArea": {
      "lonexpiresOn": -0.1286061268139623"2021-01-28T23:20:06.232134+00:00",
      "id": 1,
       },"granularity": "Position",
      "location": {
        "occupancyStatuslat": "Occupied"51.49393,
              "statusChangeTime": "2021-01-28T23:17:38.400+00:00"
 "lon": -0.12903
      },
   }   "radius": 500
    }
 ], }
}

Code Block
languagejson
{
  "data": {
    "

summary

updateSubscriptionArea": {
      "expiresOn": "2021-01-28T23:25:06.232134+00:00",
      "

undefined

id": 

0

1,
    }
  }
}

Use cases

Query

Use case

Code Block
languagegraphql
query MyQuery {
  
"total": 1
findGroupOccupancies(
    lat: 0.0, 
    lon: 0.0, 
    
"occupied"
radius: 
1,
2000
  ) {
    location {
  
"available":
  
0
  lat
      lon
 
}
   }
    summary 
}
{
      
]
available
    }
  }
}

updateSubscriptionArea

This mutation will update an existing subscription area.

Info

All subscription area updates will extend expiration by 5 minutes from the current time.

You can also send empty mutation to only update the expiration.

Mutation
Info

The summary object should be used to display availability for all parking group types

Displaying all parking groups within 2km in a mobile app

Image Added

Code Block
languagegraphql
mutation
query 
MyMutation
MyQuery {
  
updateSubscriptionArea
findGroupOccupancies(zoneId: [1607]) {
  
id: 1,
  id
    name
    positionsOccupancy 
granularity: Position,
{
      occupancyStatus
 
radius:
 
500
   
)
 
{
labels
    
expiresOn
}
    
id
summary {
   
granularity
   available
 
location
 
{
    occupied
  
lat
    total
  
lon
    undefined
}
    }
radius
  
} }

 

}
}

Getting group occupancy summary and each position status and labels to be able to calculate occupancy statistics by labels using only one query

Code Block
languagegraphql
mutation
query 
ExtendSubscription
MyQuery {
  
updateSubscriptionArea
groupOccupancy(
id: 1
,
) {
    
expiresOn
positionsOccupancy {
   
id
   
} }

Response

Code Block
languagejson
location {
  
"data":
 
{
     
"updateSubscriptionArea":
lat
{
       
"expiresOn": "2021-01-28T23:20:06.232134+00:00",
 lon
      
"id": 1,
}
      occupancyStatus
"granularity":
 
"Position",
   }
  
"location":
}
}

Displaying individual parking positions when a user approaches his desired parking location

Image Added
Code Block
languagegraphql
query MyQuery {
  
findPositionOccupancies(
    
"
lat
"
: 
51
0.
49393
0,
 
    
"
lon
"
: 
-
0.
12903
0, 
    radius: 
}
2000,
    
"radius"
labels: 
500
['Disabled']
  ) {
}
   
} } Code Block
languagejson
{
 id
  
"data":
 
{
 
location {
 
"updateSubscriptionArea":
 
{
    lat
  
"expiresOn":
 
"2021-01-28T23:25:06.232134+00:00",
   lon
   
"id": 1,
 }
    
}

Query

Use case

occupancyStatus
  }
}

Use cases

Displaying occupancy statuses of positions with label “Disabled” within 2km radius

Code Block
languagegraphql
query
mutation 
MyQuery
MyMutation {
  
findGroupOccupancies
createSubscriptionArea(
    
lat
granularity: 
0.0
Position, 
    
lon
lat: 
0
1.
0, radius: 2000 ) {
5, 
    
location {
lon: 1.5, 
    radius: 
lat
2000
  ) {
  
lon
  id
  }
}
subscription MySubscription 
summary
{
  onSubscriptionAreaUpdates(
  id: 
available
<id from previous mutation>
 
}
 
}
)
}
InfoThe summary object should be used to display availability for all parking group types

Displaying

all

live parking

groups

statuses within 2km

in a mobile appImage Removed

radius

Code Block
languagegraphql
query MyQuery { groupOccupancy(id: 1) { positionsOccupancy {
mutation LevelOccuppancyMutation {
  createSubscriptionArea(
 
location
 
{
  zoneId: 3, 
    
lat
granularity: Level
  ) {
   
lon
 id
  }
}
subscription 
}
MySubscription {
  onSubscriptionAreaUpdates(
  
occupancyStatus
id: <id from previous 
}
mutation>
  
}
)
}

Displaying

individual parking positions when a user approaches his desired parking locationImage Removed

live occupancies per level in a zone (multistory car park)

Image Added
Code Block
languagegraphql
mutation 
MyMutation
LevelOccuppancyDisabledMutation {
  createSubscriptionArea(
    
granularity
zoneId: 
Position
3, 
    
lat
labels: 
1.5
"Disabled",
    
lon: 1.5, radius
granularity: 
2000
Level
  ) {
    id
  }
}
subscription MySubscription {
  onSubscriptionAreaUpdates(
  id: <id from previous mutation>
  )
}

Displaying live

parking statuses within 2km radius

occupancies of disabled spaces per level in a zone

Image Added

Code Block
languagegraphql
mutation MyMutation {
  updateSubscriptionArea(
    id: 1, 
  ) {
    expiresOn
    id
  }
}

Extend subscription area expiration

Postman Collection

Download Postman Collection here:

View file
nameGraphQL Occupancy.postman_collection.json

Importing Collection

  1. Click import in My Workspace section.

  1. Upload the collection file and click

Import.

Adding API key to Postman Environment

This collection uses the api_key variable to add an authorization token to the x-api-key header.

  1. To create a new environment click on the eye icon near the top right corner.

2. Click Add to add a new environment.

3. Add the gql_api_key variable name and your token in the initial value.

4. Select the New Environment from the list.

5. You can now test the requests in the GraphQL Occupancy Collection.

Example Python Client

There is a simple GraphQL client example in our Github repository. It is developed in Python and let you start getting data on demand and subscribe on occupancy change notifications.

Please, follow the instructions in the README.md to prepare your invironment for running example.

https://github.com/nwaveio/graphql_occupancy_example