From 08a4761829d8aa7e1a1baf9821582d087cb9c475 Mon Sep 17 00:00:00 2001 From: Jaspreet Sachdev Date: Thu, 23 Jun 2022 20:18:23 +0000 Subject: [PATCH] GitBook: [#4] No subject --- .gitbook/assets/image (22) (1) (1).png | Bin 0 -> 128047 bytes .gitbook/assets/owanalytics.yaml | 1409 ++++++++ .gitbook/assets/owprov (1).yaml | 3081 +++++++++++++++++ .gitbook/assets/owprov.yaml | 1453 +++++++- SUMMARY.md | 5 +- api/analytics-service.md | 5 + api/provisioning-service.md | 208 +- .../expresswifi.md | 2 +- getting-started/access-points/README.md | 2 +- .../access-points/local-device-settings.md | 18 +- monitoring/elk-integration.md | 2 +- provisioning/README.md | 2 +- provisioning/data-model-introduction.md | 2 +- user-interface/README.md | 16 +- user-interface/devices-view/README.md | 14 +- .../devices-view/command-history.md | 10 +- user-interface/devices-view/commands.md | 20 +- user-interface/devices-view/statistics.md | 10 +- user-interface/firmware.md | 8 +- 19 files changed, 6010 insertions(+), 257 deletions(-) create mode 100644 .gitbook/assets/image (22) (1) (1).png create mode 100644 .gitbook/assets/owanalytics.yaml create mode 100644 .gitbook/assets/owprov (1).yaml create mode 100644 api/analytics-service.md diff --git a/.gitbook/assets/image (22) (1) (1).png b/.gitbook/assets/image (22) (1) (1).png new file mode 100644 index 0000000000000000000000000000000000000000..69ddbdff212fb21a5f7ec40a9c04445a68906660 GIT binary patch literal 128047 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 literal 0 HcmV?d00001 diff --git a/.gitbook/assets/owanalytics.yaml b/.gitbook/assets/owanalytics.yaml new file mode 100644 index 0000000..b7ccb84 --- /dev/null +++ b/.gitbook/assets/owanalytics.yaml @@ -0,0 +1,1409 @@ +openapi: 3.0.1 +info: + title: OpenWiFi Analytics Service + description: Definitions and APIs to analyze OpenWiFi network. + version: 2.6.0 + license: + name: BSD3 + url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE + +servers: + - url: 'https://localhost:16009/api/v1' + +security: + - bearerAuth: [] + - ApiKeyAuth: [] + +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: X-API-KEY + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + responses: + NotFound: + description: The specified resource was not found. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: string + + Unauthorized: + description: The requested does not have sufficient rights to perform the operation. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + enum: + - 0 # Success + - 1 # PASSWORD_CHANGE_REQUIRED, + - 2 # INVALID_CREDENTIALS, + - 3 # PASSWORD_ALREADY_USED, + - 4 # USERNAME_PENDING_VERIFICATION, + - 5 # PASSWORD_INVALID, + - 6 # INTERNAL_ERROR, + - 7 # ACCESS_DENIED, + - 8 # INVALID_TOKEN + - 9 # EXPIRED_TOKEN + - 10 # RATE_LIMIT_EXCEEDED + - 11 # BAD_MFA_TRANSACTION + - 12 # MFA_FAILURE + - 13 # SECURITY_SERVICE_UNREACHABLE + ErrorDetails: + type: string + ErrorDescription: + type: string + + Success: + description: The requested operation was performed. + content: + application/json: + schema: + properties: + Operation: + type: string + Details: + type: string + Code: + type: integer + + BadRequest: + description: The requested operation failed. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: integer + + schemas: + ObjectInfo: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + notes: + type: array + items: + $ref: '#/components/schemas/NoteInfo' + created: + type: integer + format: int64 + modified: + type: integer + format: int64 + tags: + type: array + items: + type: integer + format: int64 + + VenueInfo: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + retention: + type: integer + interval: + type: integer + monitorSubVenues: + type: boolean + + BoardInfo: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + venueList: + type: array + items: + $ref: '#/components/schemas/VenueInfo' + + BoardInfoList: + type: object + properties: + boards: + type: array + items: + $ref: '#/components/schemas/BoardInfo' + + DeviceInfo: + type: object + properties: + type: + type: string + enum: + - ap + - switch + - iot + - unknown + serialNumber: + type: string + deviceType: + type: string + lastHealth: + type: integer + format: int64 + health: + type: integer + format: int64 + lastContact: + type: integer + format: int64 + lastPing: + type: integer + format: int64 + lastState: + type: integer + format: int64 + lastFirmwareUpdate: + type: integer + format: int64 + lastFirmware: + type: string + lastConnection: + type: integer + format: int64 + lastDisconnection: + type: integer + format: int64 + pings: + type: integer + format: int64 + states: + type: integer + format: int64 + connected: + type: boolean + connectionIp: + type: string + associations_2g: + type: integer + format: int64 + associations_5g: + type: integer + format: int64 + associations_6g: + type: integer + format: int64 + locale: + type: string + memory: + type: number + uptime: + type: integer + format: int64 + + DeviceInfoList: + type: object + properties: + devices: + type: array + items: + $ref: '#/components/schemas/DeviceInfo' + + TIDstat_entry: + type: object + properties: + rx_msdu: + type: integer + format: int64 + tx_msdu: + type: integer + format: int64 + tx_msdu_failed: + type: integer + format: int64 + tx_msdu_retries: + type: integer + format: int64 + + UE_rate: + type: object + properties: + bitrate: + type: integer + format: int64 + mcs: + type: integer + format: int64 + nss: + type: integer + format: int64 + chwidth: + type: integer + format: int64 + ht: + type: boolean + sgi: + type: + boolean + + UETimePoint: + type: object + properties: + association_bssid: + type: integer + format: int64 + station: + type: integer + format: int64 + rssi: + type: integer + format: int64 + tx_bytes: + type: integer + format: int64 + rx_bytes: + type: integer + format: int64 + tx_duration: + type: integer + format: int64 + rx_packets: + type: integer + format: int64 + tx_packets: + type: integer + format: int64 + tx_retries: + type: integer + format: int64 + tx_failed: + type: integer + format: int64 + connected: + type: integer + format: int64 + inactive: + type: integer + format: int64 + tx_rate: + $ref: '#/components/schemas/UE_rate' + rx_rate: + $ref: '#/components/schemas/UE_rate' + tidstats: + type: array + items: + $ref: '#/components/schemas/TIDstat_entry' + tx_bytes_bw: + type: number + rx_bytes_bw: + type: number + tx_packets_bw: + type: number + rx_packets_bw: + type: number + tx_failed_pct: + type: number + tx_retries_pct: + type: number + tx_duration_pct: + type: number + tx_bytes_delta: + type: integer + format: int64 + rx_bytes_delta: + type: integer + format: int64 + tx_packets_delta: + type: integer + format: int64 + rx_packets_delta: + type: integer + format: int64 + tx_failed_delta: + type: integer + format: int64 + tx_retries_delta: + type: integer + format: int64 + tx_duration_delta: + type: integer + format: int64 + + AveragePoint: + type: object + properties: + min: + type: number + max: + type: number + avg: + type: number + + SSIDTimePoint: + type: object + properties: + bssid: + type: string + mode: + type: string + ssid: + type: string + band: + type: integer + associations: + type: array + items: + $ref: '#/components/schemas/UETimePoint' + tx_bytes_bw: + $ref: '#/components/schemas/AveragePoint' + rx_bytes_bw: + $ref: '#/components/schemas/AveragePoint' + tx_packets_bw: + $ref: '#/components/schemas/AveragePoint' + rx_packets_bw: + $ref: '#/components/schemas/AveragePoint' + tx_failed_pct: + $ref: '#/components/schemas/AveragePoint' + tx_retries_pct: + $ref: '#/components/schemas/AveragePoint' + tx_duration_pct: + $ref: '#/components/schemas/AveragePoint' + + APTimePoint: + type: object + properties: + collisions: + type: integer + format: int64 + multicast: + type: integer + format: int64 + rx_bytes: + type: integer + format: int64 + rx_dropped: + type: integer + format: int64 + rx_errors: + type: integer + format: int64 + rx_packets: + type: integer + format: int64 + tx_bytes: + type: integer + format: int64 + tx_dropped: + type: integer + format: int64 + tx_errors: + type: integer + format: int64 + tx_packets: + type: integer + format: int64 + tx_bytes_delta: + type: integer + format: int64 + rx_bytes_delta: + type: integer + format: int64 + rx_dropped_delta: + type: integer + format: int64 + tx_dropped_delta: + type: integer + format: int64 + rx_packets_delta: + type: integer + format: int64 + tx_packets_delta: + type: integer + format: int64 + rx_errors_delta: + type: integer + format: int64 + tx_errors_delta: + type: integer + format: int64 + + RadioTimePoint: + type: object + properties: + band: + type: integer + format: int64 + radio_channel: + type: integer + format: int64 + active_ms: + type: integer + format: int64 + busy_ms: + type: integer + format: int64 + receive_ms: + type: integer + format: int64 + transmit_ms: + type: integer + format: int64 + tx_power: + type: integer + format: int64 + channel: + type: integer + format: int64 + temperature: + type: integer + format: int64 + noise: + type: integer + format: int64 + active_pct: + type: number + busy_pct: + type: number + receive_pct: + type: number + transmit_pct: + type: number + + DeviceTimePoint: + type: object + properties: + id: + type: string + format: uuid + boardId: + type: string + format: uuid + serialNumber: + type: string + timestamp: + type: integer + format: int64 + ap_data: + $ref: '#/components/schemas/APTimePoint' + ssid_data: + type: array + items: + $ref: '#/components/schemas/SSIDTimePoint' + radio_data: + type: array + items: + $ref: '#/components/schemas/RadioTimePoint' + device_info: + $ref: '#/components/schemas/DeviceInfo' + + DeviceTimePointAnalysis: + type: object + properties: + timestamp: + type: integer + format: int64 + noise: + $ref: '#/components/schemas/AveragePoint' + active_pct: + $ref: '#/components/schemas/AveragePoint' + busy_pct: + $ref: '#/components/schemas/AveragePoint' + receive_pct: + $ref: '#/components/schemas/AveragePoint' + transmit_pct: + $ref: '#/components/schemas/AveragePoint' + tx_power: + $ref: '#/components/schemas/AveragePoint' + tx_bytes_bw: + $ref: '#/components/schemas/AveragePoint' + rx_bytes_bw: + $ref: '#/components/schemas/AveragePoint' + rx_dropped_pct: + $ref: '#/components/schemas/AveragePoint' + tx_dropped_pct: + $ref: '#/components/schemas/AveragePoint' + rx_packets_bw: + $ref: '#/components/schemas/AveragePoint' + tx_packets_bw: + $ref: '#/components/schemas/AveragePoint' + rx_errors_pct: + $ref: '#/components/schemas/AveragePoint' + tx_errors_pct: + $ref: '#/components/schemas/AveragePoint' + + DeviceTimePointList: + type: object + properties: + points: + type: array + items: + $ref: '#/components/schemas/DeviceTimePoint' + stats: + type: array + items: + $ref: '#/components/schemas/DeviceTimePointAnalysis' + + DeviceTimePointStats: + type: object + properties: + firstPoint: + type: integer + format: int64 + lastPoint: + type: integer + format: int64 + count: + type: integer + format: int64 + + WifiClientHistory: + type: object + properties: + timestamp: + type: integer + station_id: + type: string + bssid: + type: string + ssid: + type: string + rssi: + type: integer + rx_bitrate: + type: integer + rx_chwidth: + type: integer + rx_mcs: + type: integer + rx_nss: + type: integer + rx_vht: + type: boolean + tx_bitrate: + type: integer + tx_chwidth: + type: integer + tx_mcs: + type: integer + tx_nss: + type: integer + tx_vht: + type: boolean + rx_bytes: + type: integer + tx_bytes: + type: integer + rx_duration: + type: integer + tx_duration: + type: integer + rx_packets: + type: integer + tx_packets: + type: integer + ipv4: + type: string + ipv6: + type: string + channel_width: + type: integer + noise: + type: integer + tx_power: + type: integer + channel: + type: integer + active_ms: + type: integer + busy_ms: + type: integer + receive_ms: + type: integer + mode: + type: string + ack_signal: + type: integer + ack_signal_avg: + type: integer + connected: + type: integer + inactive: + type: integer + tx_retries: + type: integer + venue_id: + type: string + + WifiClientHistoryList: + type: object + properties: + entries: + type: array + items: + $ref: '#/components/schemas/WifiClientHistory' + + MacList: + type: object + properties: + entries: + type: array + items: + type: string + + ######################################################################################### + ## + ## These are endpoints that all services in the OPenWiFI stack must provide + ## + ######################################################################################### + AnyPayload: + type: object + properties: + Document: + type: string + + StringList: + type: object + properties: + list: + type: array + items: + type: string + + TagValuePair: + type: object + properties: + tag: + type: string + value: + type: string + + TagValuePairList: + type: object + properties: + tagList: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + TagIntPair: + type: object + properties: + tag: + type: string + value: + type: integer + format: int64 + + TagIntPairList: + type: object + properties: + tagList: + type: array + items: + $ref: '#/components/schemas/TagIntPair' + + SystemCommandDetails: + type: object + properties: + command: + type: string + enum: + - setloglevels + - getloglevels + - getSubSystemNames + - getLogLevelNames + - stats + parameters: + oneOf: + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + + SystemCommandResults: + type: object + oneOf: + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + + NoteInfo: + type: object + properties: + created: + type: integer + format: int64 + createdBy: + type: string + note: + type: string + + SystemInfoResults: + type: object + properties: + version: + type: string + uptime: + type: integer + format: integer64 + start: + type: integer + format: integer64 + os: + type: string + processors: + type: integer + hostname: + type: string + certificates: + type: array + items: + type: object + properties: + filename: + type: string + expires: + type: integer + format: int64 + + Dashboard: + type: object + properties: + snapshot: + type: integer + format: int64 + tenants: + $ref: '#/components/schemas/TagIntPairList' + + SystemCommandSetLogLevel: + type: object + properties: + command: + type: string + enum: + - setloglevel + subsystems: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + SystemCommandReload: + type: object + properties: + command: + type: string + enum: + - reload + subsystems: + type: array + items: + type: string + example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult. + + SystemCommandGetLogLevels: + type: object + properties: + command: + type: string + enum: + - getloglevels + + SystemGetLogLevelsResult: + type: object + properties: + taglist: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + SystemCommandGetLogLevelNames: + type: object + properties: + command: + type: string + enum: + - getloglevelnames + + SystemCommandGetSubsystemNames: + type: object + properties: + command: + type: string + enum: + - getsubsystemnames + + SystemCommandGetLogLevelNamesResult: + type: object + properties: + list: + type: array + items: + type: string + + SystemGetSubSystemNamesResult: + type: object + properties: + taglist: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + +paths: + /boards: + get: + tags: + - Boards + operationId: getBoards + summary: Retrieve a list of boards. + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: return the number of boards + name: countOnly + schema: + type: boolean + required: false + - in: query + description: list of boards for a given venue + name: forVenue + schema: + type: string + format: uuid + required: false + responses: + 200: + description: Return a list of boards + content: + application/json: + schema: + $ref: '#/components/schemas/BoardInfoList' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /board/{id}: + get: + tags: + - Boards + operationId: getBoard + summary: Retrieve a board + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + responses: + 200: + description: Return a list of boards + content: + application/json: + schema: + $ref: '#/components/schemas/BoardInfo' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + tags: + - Boards + operationId: deleteBoard + summary: Remove a board + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + tags: + - Boards + operationId: createBoard + summary: Create a board + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + example: value should be 0 for a post + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BoardInfo' + responses: + 200: + $ref: '#/components/schemas/BoardInfo' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + put: + tags: + - Boards + operationId: modifyBoard + summary: Modify a board + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BoardInfo' + responses: + 200: + $ref: '#/components/schemas/BoardInfo' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /board/{id}/devices: + get: + tags: + - Board Devices + summary: Get basic information about all the devices for a venue. + operationId: getBoardDevices + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + + responses: + 200: + $ref: '#/components/schemas/DeviceInfoList' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /board/{id}/timepoints: + get: + tags: + - Board data + summary: retrieve board data for a given time period. + operationId: getBoardTimepoint + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + - in: query + name: fromDate + schema: + type: integer + required: false + - in: query + name: endDate + schema: + type: integer + required: false + - in: query + name: maxRecords + schema: + type: integer + default: 100 + required: false + - in: query + name: statsOnly + schema: + type: boolean + default: false + required: false + - in: query + name: pointsOnly + schema: + type: boolean + default: false + required: false + - in: query + name: pointsStatsOnly + schema: + type: boolean + default: false + required: false + + responses: + 200: + $ref: '#/components/schemas/DeviceTimePointList' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Board data + summary: delete board data for a given time period. + operationId: deleteBoardTimepoints + parameters: + - in: path + name: id + schema: + type: string + format: uuid + required: true + - in: query + name: fromDate + schema: + type: integer + required: false + - in: query + name: endDate + schema: + type: integer + required: false + responses: + 200: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + + /iptocountry: + get: + tags: + - Utility + summary: Get the country code for an IP address + operationId: getIpToCountry + parameters: + - in: query + name: iplist + schema: + type: string + example: + 10.2.2.2,10.3.4.3 + required: true + responses: + 200: + description: List of country codes. + content: + application/json: + schema: + type: object + properties: + enabled: + type: boolean + countryCodes: + type: array + items: + type: string + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /wifiClientHistory: + get: + tags: + - WiFiClientHistory + operationId: getWifiClientHistory + summary: Retrieve WiFi client history for debugging purpose + parameters: + - in: query + name: fromDate + schema: + type: integer + required: false + - in: query + name: endDate + schema: + type: integer + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: macsOnly + schema: + type: boolean + default: false + required: true + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: macFilter + schema: + type: string + example: + 112233445566, 11223344*, *5566 + required: false + - in: query + description: The venue to for the search. + name: venue + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/schemas/StringList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /wifiClientHistory/{client}: + get: + tags: + - WiFiClientHistory + operationId: getWifiClients + summary: Retrieve WiFi client history for debugging purpose + parameters: + - in: path + name: client + schema: + type: string + example: + "112233aabbcc" + required: true + - in: query + name: fromDate + schema: + type: integer + required: false + - in: query + name: endDate + schema: + type: integer + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: The venue to for the search. + name: venue + schema: + type: string + format: uuid + required: true + - in: query + description: return extended information + name: orderBy + schema: + type: string + example: serialNumber:a,created:d + required: false + - in: query + description: return extended information + name: orderSpec + schema: + type: boolean + default: false + required: false + responses: + 200: + $ref: '#/components/schemas/WifiClientHistoryList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - WiFiClientHistory + operationId: deleteWifiClientHistory + summary: Retrieve WiFi client history for debugging purpose + parameters: + - in: query + description: The venue to for the search. + name: venue + schema: + type: string + format: uuid + required: true + - in: path + name: client + schema: + type: string + example: + "112233aabbcc" + required: true + - in: query + name: fromDate + schema: + type: integer + required: false + - in: query + name: endDate + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: macFilter + schema: + type: string + example: + 112233445566, 11223344*, *5566 + required: false + responses: + 200: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + ######################################################################################### + ## + ## These are endpoints that all services in the OpenWiFi stack must provide + ## + ######################################################################################### + /system: + post: + tags: + - System Commands + summary: Perform some system wide commands. + operationId: systemCommand + requestBody: + description: Command details + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SystemCommandSetLogLevel' + - $ref: '#/components/schemas/SystemCommandReload' + - $ref: '#/components/schemas/SystemCommandGetLogLevels' + - $ref: '#/components/schemas/SystemCommandGetLogLevelNames' + - $ref: '#/components/schemas/SystemCommandGetSubsystemNames' + responses: + 200: + description: Successful command execution + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SystemGetLogLevelsResult' + - $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult' + - $ref: '#/components/schemas/SystemGetSubSystemNamesResult' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + get: + tags: + - System Commands + summary: Retrieve different values from the running service. + operationId: getSystemCommand + parameters: + - in: query + description: Get a value + name: command + schema: + type: string + enum: + - info + required: true + + responses: + 200: + description: Successful command execution + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SystemInfoResults' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' diff --git a/.gitbook/assets/owprov (1).yaml b/.gitbook/assets/owprov (1).yaml new file mode 100644 index 0000000..7f55715 --- /dev/null +++ b/.gitbook/assets/owprov (1).yaml @@ -0,0 +1,3081 @@ +openapi: 3.0.1 +info: + title: OpenWiFi Provisioning Model + description: Definitions and APIs to manages an OpenWiFi network. + version: 2.5.0 + license: + name: BSD3 + url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE + +servers: + - url: 'https://localhost:16005/api/v1' + +security: + - bearerAuth: [] + - ApiKeyAuth: [] + +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: X-API-KEY + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + responses: + NotFound: + description: The specified resource was not found. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: string + + Unauthorized: + description: The requested does not have sufficient rights to perform the operation. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + enum: + - 0 # Success + - 1 # PASSWORD_CHANGE_REQUIRED, + - 2 # INVALID_CREDENTIALS, + - 3 # PASSWORD_ALREADY_USED, + - 4 # USERNAME_PENDING_VERIFICATION, + - 5 # PASSWORD_INVALID, + - 6 # INTERNAL_ERROR, + - 7 # ACCESS_DENIED, + - 8 # INVALID_TOKEN + - 9 # EXPIRED_TOKEN + - 10 # RATE_LIMIT_EXCEEDED + - 11 # BAD_MFA_TRANSACTION + - 12 # MFA_FAILURE + - 13 # SECURITY_SERVICE_UNREACHABLE + ErrorDetails: + type: string + ErrorDescription: + type: string + + Success: + description: The requested operation was performed. + content: + application/json: + schema: + properties: + Operation: + type: string + Details: + type: string + Code: + type: integer + + BadRequest: + description: The requested operation failed. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: integer + + schemas: + + ObjectInfo: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + notes: + type: array + items: + $ref: '#/components/schemas/NoteInfo' + created: + type: integer + format: int64 + modified: + type: integer + format: int64 + tags: + type: array + items: + type: integer + format: int64 + + # uuids: mpe: + ManagementPolicyEntry: + type: object + properties: + users: + type: array + items: + type: string + resources: + description: this is a list of UUID and UUID Patterns to control by this policy + type: array + items: + type: string + access: + type: array + items: + type: string + enum: + - NOACCESS + - READ + - MODIFY + - DELETE + - LIST + - CREATE + - FULL + policy: + description: A JSON document describing the policy + type: string + + # uuids: mpp: + ManagementPolicy: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + entries: + type: array + items: + $ref: '#/components/schemas/ManagementPolicyEntry' + inUse: + type: array + items: + type: string + format: uuid + example: each uuid is preceded by ent, or ven to say that the elemenet is entity or venue + entity: + type: string + format: uuid + venue: + type: string + format: uuid + + ManagementPolicyList: + type: object + properties: + policies: + type: array + items: + $ref: '#/components/schemas/ManagementPolicy' + + # uuids: ent: + Entity: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + parent: + description: If empty, then this is the root entity, otherwise this points to a parent entity + type: string + format: uuid + children: + type: array + items: + type: string + format: uuid + venues: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + contacts: + description: The list of UUID of the contacts for the entity + type: array + items: + type: string + format: uuid + locations: + description: The list of UUID of the locations associated with thit entiry + type: array + items: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + deviceConfiguration: + type: string + format: uuid + devices: + type: array + items: + type: string + format: uuid + managementPolicies: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + variables: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + managementRoles: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + maps: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + configurations: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + rrm: + type: string + enum: + - off + - on + - inherit + sourceIP: + $ref: '#/components/schemas/StringList' + + EntityList: + type: object + properties: + entities: + type: array + items: + $ref: '#/components/schemas/Entity' + + DiGraphEntry: + type: object + properties: + parent: + type: string + format: uuid + child: + type: string + format: uuid + + DiGraph: + type: array + items: + $ref: '#/components/schemas/DiGraphEntry' + + # uuids: ven: + Venue: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + entity: + type: string + format: uuid + parent: + type: string + format: uuid + children: + type: array + items: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + devices: + type: array + items: + type: string + format: uuid + topology: + $ref: '#/components/schemas/DiGraph' + design: + type: string + deviceConfiguration: + type: string + format: uuid + contacts: + type: array + items: + type: string + format: uuid + location: + type: string + format: uuid + rrm: + type: string + enum: + - off + - on + - inherit + sourceIP: + $ref: '#/components/schemas/StringList' + managementPolicies: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + managementRoles: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + variables: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + maps: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + configurations: + description: The list of UUID of the venues for this entity + type: array + items: + type: string + format: uuid + + VenueList: + type: object + properties: + venues: + type: array + items: + $ref: '#/components/schemas/Venue' + + UserInfoDigest: + type: object + properties: + id: + type: string + format: uuid + loginId: + type: string + type: + type: string + + # uuids: mgg: + ManagementRole: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + managementPolicy: + type: string + format: uuid + users: + type: array + items: + type: string + format: uuid + inUse: + type: array + items: + type: string + format: uuid + example: each uuid is preceded by ent, or ven to say that the elemenet is entity or venue + entity: + type: string + format: uuid + venue: + type: string + format: uuid + + ManagementRoleList: + type: object + properties: + roles: + type: array + items: + $ref: '#/components/schemas/ManagementRole' + + # uuids: loc: + Location: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + type: + type: string + enum: + - SERVICE + - EQUIPMENT + - AUTO + - MANUAL + - SPECIAL + - UNKNOWN + - CORPORATE + buildingName: + type: string + addressLines: + type: array + items: + type: string + city: + type: string + state: + type: string + postal: + type: string + country: + type: string + phones: + type: array + items: + type: string + mobiles: + type: array + items: + type: string + inUse: + type: array + items: + type: string + format: uuid + example: each uuid is preceded by ent, or ven to say that the elemenet is entity or venue + entity: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + geoCode: + type: string + + LocationList: + type: object + properties: + locations: + type: array + items: + $ref: '#/components/schemas/Location' + + # uuids: con: + Contact: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + type: + type: string + enum: + - SUBSCRIBER + - USER + - INSTALLER + - CSR + - MANAGER + - BUSINESSOWNER + - TECHNICIAN + - CORPORATE + title: + type: string + salutation: + type: string + firstname: + type: string + lastname: + type: string + initials: + type: string + visual: + type: string + phones: + type: array + items: + type: string + mobiles: + type: array + items: + type: string + primaryEmail: + type: string + secondaryEmail: + type: string + accessPIN: + type: string + inUse: + type: array + items: + type: string + format: uuid + entity: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + + ContactList: + type: object + properties: + contacts: + type: array + items: + $ref: '#/components/schemas/Contact' + + DeviceConfigurationElement: + type: object + properties: + name: + type: string + description: + type: string + weight: + type: integer + configuration: + type: string + + DeviceConfiguration: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + managementPolicy: + type: string + format: uuid + deviceTypes: + type: array + items: + type: string + configuration: + type: array + items: + $ref: '#/components/schemas/DeviceConfigurationElement' + variables: + type: array + items: + type: string + format: uuid + inUse: + type: array + items: + type: string + format: uuid + subscriberOnly: + type: boolean + default: false + rrm: + type: string + enum: + - off + - on + - inherit + firmwareUpgrade: + type: string + example: auto or a time string of the format DOW-HH:MM + firmwareRCOnly: + type: boolean + venue: + type: string + format: uuid + entity: + type: string + format: uuid + subscriber: + type: string + format: uuid + + DeviceConfigurationList: + type: object + properties: + configurations: + type: array + items: + $ref: '#/components/schemas/DeviceConfiguration' + + InventoryTag: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + serialNumber: + type: string + deviceType: + type: string + venue: + type: string + format: uuid + entity: + type: string + format: uuid + subscriber: + type: string + format: uuid + qrCode: + type: string + geoCode: + type: string + location: + type: string + format: uuid + contact: + type: string + format: uuid + deviceConfiguration: + type: string + format: uuid + rrm: + type: string + enum: + - off + - on + - inherit + managementPolicy: + type: string + format: uuid + state: + type: string + devClass: + type: string + enum: + - any + - venue + - entity + - subscriber + locale: + type: string + minLength: 2 + maxLength: 2 + + InventoryTagList: + type: object + properties: + taglist: + type: array + items: + $ref: '#/components/schemas/InventoryTag' + + SerialNumberList: + type: object + properties: + serialNumbers: + type: array + items: + type: string + + CountAnswer: + type: object + properties: + count: + type: integer + format: int64 + + ExpandedUseEntry: + type: object + properties: + uuid: + type: string + format: uuid + name: + type: string + description: + type: string + + ExpandedUseEntryMap: + type: object + properties: + type: + type: string + entries: + type: array + items: + $ref: '#/components/schemas/ExpandedUseEntry' + + ExpandedUseEntryMapList: + type: object + properties: + entries: + type: array + items: + $ref: '#/components/schemas/ExpandedUseEntryMap' + + FirmwareOptions: + type: object + properties: + firmwareUpgrade: + type: string + example: auto or a time string of the format DOW-HH:MM + firmwareRCOnly: + type: boolean + from: + type: string + + InventoryConfigApplyResult: + type: object + properties: + appliedConfiguration: + type: string + errors: + type: array + items: + type: string + warnings: + type: array + items: + type: string + errorCode: + type: integer + + uuidList: + type: object + properties: + list: + type: array + items: + type: string + format: uuid + + ObjectACL: + type: object + properties: + users: + $ref: '#/components/schemas/uuidList' + roles: + $ref: '#/components/schemas/uuidList' + access: + type: string + enum: + - none + - read + - modify + - delete + - create + + ObjectACLList: + type: object + properties: + list: + type: array + items: + $ref: '#/components/schemas/ObjectACL' + + Map: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + entity: + type: string + format: uuid + venue: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + data: + type: string + visibility: + type: string + enum: + - private + - public + - select + creator: + type: string + format: uuid + access: + $ref: '#/components/schemas/ObjectACLList' + + MapList: + type: object + properties: + list: + type: array + items: + $ref: '#/components/schemas/Map' + + + SignupEntry: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + email: + type: string + format: email + userId: + type: string + format: uuid + macAddress: + type: string + serialNumber: + type: string + created: + type: integer + format: int64 + completed: + type: integer + format: int64 + error: + type: integer + format: int64 + status: + type: string + statusCode: + type: integer + format: int64 + + Variable: + type: object + properties: + type: + type: string + enum: + - integer + - string + - float + - boolean + - variable + - json + weight: + type: integer + format: int64 + prefix: + type: string + value: + type: string + + VariableList: + type: object + properties: + variables: + type: array + items: + $ref: '#/components/schemas/Variable' + + VariableBlock: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + variables: + type: array + items: + $ref: '#/components/schemas/Variable' + entity: + type: string + format: uuid + venue: + type: string + format: uuid + subscriber: + type: string + format: uuid + inventory: + type: string + format: uuid + inUse: + type: array + items: + type: string + format: uuid + + VariableBlockList: + type: object + properties: + variableBlocks: + type: array + items: + $ref: '#/components/schemas/VariableBlock' + + ######################################################################################### + ## + ## These are endpoints that all services in the OPenWiFI stack must provide + ## + ######################################################################################### + AnyPayload: + type: object + properties: + Document: + type: string + + StringList: + type: object + properties: + list: + type: array + items: + type: string + + TagValuePair: + type: object + properties: + tag: + type: string + value: + type: string + + TagValuePairList: + type: object + properties: + tagList: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + TagIntPair: + type: object + properties: + tag: + type: string + value: + type: integer + format: int64 + + TagIntPairList: + type: object + properties: + tagList: + type: array + items: + $ref: '#/components/schemas/TagIntPair' + + SystemCommandDetails: + type: object + properties: + command: + type: string + enum: + - setloglevels + - getloglevels + - getSubSystemNames + - getLogLevelNames + - stats + parameters: + oneOf: + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + + SystemCommandResults: + type: object + oneOf: + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + + NoteInfo: + type: object + properties: + created: + type: integer + format: int64 + createdBy: + type: string + note: + type: string + + SystemInfoResults: + type: object + properties: + version: + type: string + uptime: + type: integer + format: integer64 + start: + type: integer + format: integer64 + os: + type: string + processors: + type: integer + hostname: + type: string + certificates: + type: array + items: + type: object + properties: + filename: + type: string + expires: + type: integer + format: int64 + + Dashboard: + type: object + properties: + snapshot: + type: integer + format: int64 + tenants: + $ref: '#/components/schemas/TagIntPairList' + + SystemCommandSetLogLevel: + type: object + properties: + command: + type: string + enum: + - setloglevel + subsystems: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + SystemCommandReload: + type: object + properties: + command: + type: string + enum: + - reload + subsystems: + type: array + items: + type: string + example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult. + + SystemCommandGetLogLevels: + type: object + properties: + command: + type: string + enum: + - getloglevels + + SystemGetLogLevelsResult: + type: object + properties: + taglist: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + SystemCommandGetLogLevelNames: + type: object + properties: + command: + type: string + enum: + - getloglevelnames + + SystemCommandGetSubsystemNames: + type: object + properties: + command: + type: string + enum: + - getsubsystemnames + + SystemCommandGetLogLevelNamesResult: + type: object + properties: + list: + type: array + items: + type: string + + SystemGetSubSystemNamesResult: + type: object + properties: + taglist: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + +paths: + /entity: + get: + tags: + - Entities + operationId: getEntities + summary: Retrieve a list of entities. + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of devices comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of devices + name: countOnly + schema: + type: boolean + required: false + + responses: + 200: + description: Return a list of elements + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/EntityList' + - $ref: '#/components/schemas/CountAnswer' + + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /entity/{uuid}: + get: + tags: + - Entities + operationId: getEntity + summary: Retrieve a specific entity. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: When looking for the root entity, the uuid 0000-0000-0000 must be entered. + required: true + + responses: + 200: + $ref: '#/components/schemas/Entity' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Entities + operationId: createEntity + summary: Create a specific entity. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: When creating the root entity, the uuid 0000-0000-0000 must be entered. When creating a non-root entity, uuid must be 1 + required: true + requestBody: + description: Information used to create the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/Entity' + + responses: + 200: + $ref: '#/components/schemas/Entity' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Entities + operationId: modifyEntity + summary: Modify a specific entity. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: When modifying the root entity, the uuid 0000-0000-0000 must be entered. + required: true + requestBody: + description: Information used to modify the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/Entity' + + responses: + 200: + $ref: '#/components/schemas/Entity' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Entities + operationId: deleteEntity + summary: Delete a specific entity. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: The root entity cannot be deleted. + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /contact: + get: + tags: + - Contacts + operationId: getContacts + summary: Retrieve a list of contacts. + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of contacts comma separated + name: select + schema: + type: string + example: uuid1,uuid2,uuid3 + required: false + - in: query + description: return the number of contacts + name: countOnly + schema: + type: boolean + required: false + - in: query + description: return only the UUIDs of contacts + name: uuidOnly + schema: + type: boolean + required: false + - in: query + name: venue + schema: + type: string + format: uuid + required: false + - in: query + name: entity + schema: + type: string + format: uuid + required: false + + responses: + 200: + description: Return a list of contacts + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ContactList' + - $ref: '#/components/schemas/CountAnswer' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /contact/{uuid}: + get: + tags: + - Contacts + operationId: getContact + summary: Retrieve a specific contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: expandInUse + schema: + type: boolean + required: false + + responses: + 200: + description: Success + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Contact' + - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Contacts + operationId: createContact + summary: Create a specific entity. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/Contact' + + responses: + 200: + $ref: '#/components/schemas/Contact' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Contacts + operationId: modifyContact + summary: Modify a specific contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/Contact' + + responses: + 200: + $ref: '#/components/schemas/Contact' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Contacts + operationId: deleteContact + summary: Delete a specific contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: force + schema: + type: boolean + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /location: + get: + tags: + - Locations + operationId: getLocations + summary: Retrieve a list of locations. + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of Locations comma separated + name: select + schema: + type: string + example: uuid1,uuid2,uuid3 + required: false + - in: query + description: return the number of Locations + name: countOnly + schema: + type: boolean + required: false + - in: query + description: return only the UUIDs of Locations + name: uuidOnly + schema: + type: boolean + required: false + + responses: + 200: + description: Return a list of Locations + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/LocationList' + - $ref: '#/components/schemas/CountAnswer' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /location/{uuid}: + get: + tags: + - Locations + operationId: getLocation + summary: Retrieve a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: expandInUse + schema: + type: boolean + required: false + + responses: + 200: + description: Success + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Location' + - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Locations + operationId: createLocation + summary: Create a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new location + content: + application/json: + schema: + $ref: '#/components/schemas/Location' + + responses: + 200: + $ref: '#/components/schemas/Location' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Locations + operationId: modifyLocation + summary: Modify a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify the new location + content: + application/json: + schema: + $ref: '#/components/schemas/Location' + + responses: + 200: + $ref: '#/components/schemas/Location' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Locations + operationId: deleteLocation + summary: Delete a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: force + schema: + type: boolean + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /inventory: + get: + tags: + - Inventory + operationId: getInventoryTags + summary: Retrieve a list of inventory. + parameters: + - in: query + name: entity + schema: + type: string + format: uuid + required: false + - in: query + name: venue + schema: + type: string + format: uuid + required: false + - in: query + name: unassigned + schema: + type: boolean + required: false + - in: query + name: deviceType + schema: + type: string + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of devices comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: only serial numbers of full device details + name: serialOnly + schema: + type: boolean + required: false + - in: query + description: return the number of devices + name: countOnly + schema: + type: boolean + required: false + - in: query + description: return extended information + name: withExtendedInfo + schema: + type: boolean + required: false + - in: query + description: return extended information + name: orderBy + schema: + type: string + example: serialNumber:a,created:d + required: false + - in: query + description: return the list of devices under RRM + name: rrmOnly + schema: + type: boolean + default: false + required: false + - in: query + description: return the list of devices under RRM + name: subscriber + schema: + type: string + format: uuid + required: false + responses: + 200: + description: Return a list of elements + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SerialNumberList' + - $ref: '#/components/schemas/InventoryTagList' + - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /inventory/{serialNumber}: + get: + tags: + - Inventory + operationId: getInventory + summary: Retrieve a specific inventory tag. + parameters: + - in: path + name: serialNumber + schema: + type: string + format: uuid + required: true + - in: query + name: config + schema: + type: boolean + required: false + - in: query + name: explain + schema: + type: boolean + required: false + - in: query + name: firmwareOptions + schema: + type: boolean + required: false + - in: query + name: applyConfiguration + schema: + type: boolean + required: false + responses: + 200: + description: Succesful retrieve configuratiopn or part of the configuration + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/InventoryTag' + - $ref: '#/components/schemas/FirmwareOptions' + - $ref: '#/components/schemas/InventoryConfigApplyResult' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + tags: + - Inventory + operationId: createInventory + summary: Create a specific Inventory. + parameters: + - in: path + name: serialNumber + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/InventoryTag' + responses: + 200: + $ref: '#/components/schemas/InventoryTag' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Inventory + operationId: modifyInventory + summary: Modify a specific inventory. + parameters: + - in: path + name: serialNumber + schema: + type: string + format: uuid + required: true + - in: query + name: unassign + schema: + type: boolean + required: false + - in: path + name: removeSubscriber + schema: + type: string + format: uuid + required: true + + requestBody: + description: Information used to modify the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/InventoryTag' + + responses: + 200: + description: success + content: + application/json: + schema: + $ref: '#/components/schemas/InventoryTag' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Inventory + operationId: deleteInventory + summary: Delete a specific inventory. + parameters: + - in: path + name: serialNumber + schema: + type: string + format: uuid + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /venue: + get: + tags: + - Venues + operationId: getVenues + summary: Retrieve a list of venues. + parameters: + - in: query + name: entity + schema: + type: string + format: uuid + required: false + - in: query + name: venue + schema: + type: string + format: uuid + required: false + - in: query + name: unassigned + schema: + type: boolean + required: false + - in: query + name: deviceType + schema: + type: string + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of Venues comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: only serial numbers of full device details + name: serialOnly + schema: + type: boolean + required: false + - in: query + description: return the number of devices + name: countOnly + schema: + type: boolean + required: false + + responses: + 200: + description: Return a list of venues. + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/VenueList' + - $ref: '#/components/schemas/CountAnswer' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /venue/{uuid}: + get: + tags: + - Venues + operationId: getVenue + summary: Retrieve a specific venue. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + + responses: + 200: + $ref: '#/components/schemas/Venue' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Venues + operationId: createVenue + summary: Create a specific venue. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: createObjects + schema: + type: object + properties: + objects: + type: array + items: + oneOf: + - type: object + properties: + location: + $ref: '#/components/schemas/Location' + - type: object + properties: + contact: + $ref: '#/components/schemas/Contact' + required: false + requestBody: + description: Information used to create the new venue + content: + application/json: + schema: + $ref: '#/components/schemas/Venue' + + responses: + 200: + $ref: '#/components/schemas/Venue' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Venues + operationId: modifyVenue + summary: Modify a specific venue. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify the new venue + content: + application/json: + schema: + $ref: '#/components/schemas/Venue' + + responses: + 200: + $ref: '#/components/schemas/Venue' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Venues + operationId: deleteVenue + summary: Delete a specific venue. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: The root entity cannot be deleted. + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /map: + get: + tags: + - Maps + operationId: getMapList + summary: Retrieve the list of maps + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Return only maps I created + name: myMaps + schema: + type: boolean + required: false + - in: query + description: Return only maps shared with Me + name: sharedWithMe + schema: + type: boolean + required: false + + responses: + 200: + description: Return a list of Venues + content: + application/json: + schema: + $ref: '#/components/schemas/MapList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /map/{uuid}: + get: + tags: + - Maps + operationId: getMap + summary: Retrieve a specific map. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + + responses: + 200: + description: Successfull retrieval of a map + content: + application/json: + schema: + $ref: '#/components/schemas/Map' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Maps + operationId: createMap + summary: Create a specific map. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new policy + content: + application/json: + schema: + $ref: '#/components/schemas/Map' + + responses: + 200: + $ref: '#/components/schemas/Map' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Maps + operationId: modifyMap + summary: Modify a specific map. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify a map + content: + application/json: + schema: + $ref: '#/components/schemas/Map' + + responses: + 200: + $ref: '#/components/schemas/ManagementPolicy' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Maps + operationId: deleteMap + summary: Delete a specific map. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /managementPolicy: + get: + tags: + - Management Policies + operationId: getPolicies + summary: Get a list of policies. + parameters: + - in: query + name: entity + schema: + type: string + format: uuid + required: false + - in: query + name: venue + schema: + type: string + format: uuid + required: false + - in: query + name: unassigned + schema: + type: boolean + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of policies comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of policies + name: countOnly + schema: + type: boolean + required: false + + responses: + 200: + description: Return a list of Venues + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ManagementPolicyList' + - $ref: '#/components/schemas/CountAnswer' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /managementPolicy/{uuid}: + get: + tags: + - Management Policies + operationId: getManagementPolicy + summary: Retrieve a specific policy. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: expandInUse + schema: + type: boolean + required: false + + responses: + 200: + description: Succesful retrieve a management policy + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ManagementPolicy' + - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Management Policies + operationId: createManagementPolicy + summary: Create a specific policy. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new policy + content: + application/json: + schema: + $ref: '#/components/schemas/ManagementPolicy' + + responses: + 200: + $ref: '#/components/schemas/ManagementPolicy' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Management Policies + operationId: modifyManagementPolicy + summary: Modify a specific policy. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify the new policy. + content: + application/json: + schema: + $ref: '#/components/schemas/ManagementPolicy' + + responses: + 200: + $ref: '#/components/schemas/ManagementPolicy' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Management Policies + operationId: deleteManagementPolicy + summary: Delete a specific policy. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: The root entity cannot be deleted. + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /managementRole: + get: + tags: + - Management Roles + operationId: getManagementRoles + summary: Retrieve a list of management roles. + parameters: + - in: query + name: entity + schema: + type: string + format: uuid + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of devices comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of roles + name: countOnly + schema: + type: boolean + required: false + + responses: + 200: + description: Return a list of elements + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ManagementRoleList' + - $ref: '#/components/schemas/CountAnswer' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /managementRole/{uuid}: + get: + tags: + - Management Roles + operationId: getManagementRole + summary: Retrieve a specific management role. + parameters: + - in: path + name: uuid + required: true + schema: + type: string + format: uuid + - in: query + name: expandInUse + schema: + type: boolean + required: false + responses: + 200: + description: Success + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ManagementRole' + - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + tags: + - Management Roles + operationId: createManagementRole + summary: Create a specific management role. + parameters: + - in: path + name: uuid + required: true + schema: + type: string + format: uuid + example: during creation, must be set to 1. The real uuid will be returned in the created object + requestBody: + description: Information used to create management role + content: + application/json: + schema: + $ref: '#/components/schemas/ManagementRole' + + responses: + 200: + $ref: '#/components/schemas/ManagementRole' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Management Roles + operationId: modifyManagementRole + summary: Modify a specific management role. + parameters: + - in: path + name: uuid + required: true + schema: + type: string + format: uuid + requestBody: + description: Information used to modify management role + content: + application/json: + schema: + $ref: '#/components/schemas/ManagementRole' + + responses: + 200: + $ref: '#/components/schemas/ManagementRole' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + tags: + - Management Roles + operationId: deleteManagementRole + summary: Delete a specific management role. + parameters: + - in: path + name: uuid + required: true + schema: + type: string + format: uuid + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /configurations: + get: + tags: + - Configurations + operationId: getConfigurations + summary: Retrieve a list of configurations. + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of devices comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of devices + name: countOnly + schema: + type: boolean + required: false + - in: query + name: venue + schema: + type: string + format: uuid + required: false + - in: query + name: entity + schema: + type: string + format: uuid + required: false + + responses: + 200: + description: Return a list of elements + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/DeviceConfigurationList' + - $ref: '#/components/schemas/CountAnswer' + + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /configurations/{uuid}: + get: + tags: + - Configurations + operationId: geConfiguration + summary: Retrieve a specific configuration. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: When looking for the root entity, the uuid 0000-0000-0000 must be entered. + required: true + - in: query + name: expandInUse + schema: + type: boolean + required: false + + responses: + 200: + description: Success + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/DeviceConfiguration' + - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Configurations + operationId: createConfiguration + summary: Create a specific configuration. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: When creating the root entity, the uuid 0000-0000-0000 must be entered. When creating a non-root entity, uuid must be 1 + required: true + - in: query + name: validateOnly + schema: + type: boolean + required: false + requestBody: + description: Information used to create the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceConfiguration' + + responses: + 200: + $ref: '#/components/schemas/DeviceConfiguration' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Configurations + operationId: modifyConfiguration + summary: Modify a specific configuration. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: When modifying the root entity, the uuid 0000-0000-0000 must be entered. + required: true + requestBody: + description: Information used to modify the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceConfiguration' + + responses: + 200: + $ref: '#/components/schemas/DeviceConfiguration' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Configurations + operationId: deleteConfiguration + summary: Delete a specific configuration. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: The root entity cannot be deleted. + required: true + + responses: + 204: + $ref: '#/components/responses/Success' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /iptocountry: + get: + tags: + - Utility + summary: Get the country code for an IP address + operationId: getIpToCountry + parameters: + - in: query + name: iplist + schema: + type: string + example: + 10.2.2.2,10.3.4.3 + required: true + responses: + 200: + description: List of country codes. + content: + application/json: + schema: + type: object + properties: + enabled: + type: boolean + countryCodes: + type: array + items: + type: string + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /signup: + get: + tags: + - Subscriber Registration + summary: This call allows someone to get the status of a signup. + operationId: getSignup + parameters: + - in: query + name: email + schema: + type: string + format: email + required: false + - in: query + name: macAddress + schema: + type: string + required: false + - in: query + name: signupUUID + schema: + type: string + format: uuid + required: false + - in: query + name: dashboard + schema: + type: boolean + default: false + required: false + - in: query + name: deviceID + schema: + type: string + required: false + responses: + 200: + description: Successfull completion + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SignupEntry' + - $ref: '#/components/schemas/Dashboard' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Subscriber Registration + summary: This call allows someone to delete a specific signUp or all signups according to serialNumber of email address + operationId: deleteSignup + parameters: + - in: query + name: email + schema: + type: string + format: email + required: false + - in: query + name: macAddress + schema: + type: string + required: false + - in: query + name: signupUUID + schema: + type: string + format: uuid + required: false + - in: query + name: deviceID + schema: + type: string + required: false + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + post: + tags: + - Subscriber Registration + summary: This call allows a new subscriber to register themselves and their devices. + operationId: postSignup + parameters: + - in: query + name: email + schema: + type: string + format: email + required: true + - in: query + name: macAddress + schema: + type: string + required: true + - in: query + name: deviceID + schema: + type: string + required: false + responses: + 200: + $ref: '#/components/schemas/SignupEntry' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + put: + tags: + - Subscriber Registration + summary: modify the signup command in play + operationId: modifySignup + parameters: + - in: query + name: signupUUID + schema: + type: string + format: uuid + required: true + - in: query + name: operation + schema: + type: string + enum: + - cancel + - emailVerified + - deviceVerified + required: true + requestBody: + content: + application/json: + schema: + type: object + properties: + reason: + type: string + time: + type: integer + format: int64 + errorCode: + type: integer + format: int32 + status: + type: string + required: false + + responses: + 200: + $ref: '#/components/schemas/SignupEntry' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /variables: + get: + tags: + - Variable Configuration Blocks + summary: Retrieve lists of control blocks + operationId: getVariableList + parameters: + - in: query + name: venue + schema: + type: string + format: uuid + required: false + - in: query + name: entity + schema: + type: string + format: uuid + required: false + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of devices comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of devices + name: countOnly + schema: + type: boolean + required: false + responses: + 200: + $ref: '#/components/schemas/VariableBlockList' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + ######################################################################################### + ## + ## These are endpoints that all services in the OpenWiFi stack must provide + ## + ######################################################################################### + /dashboard: + get: + tags: + - Dashboards + summary: Get the last version of the dashboard. + operationId: getDeviceDashboard + responses: + 200: + $ref: '#/components/schemas/Dashboard' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /system: + post: + tags: + - System Commands + summary: Perform some system wide commands. + operationId: systemCommand + requestBody: + description: Command details + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SystemCommandSetLogLevel' + - $ref: '#/components/schemas/SystemCommandReload' + - $ref: '#/components/schemas/SystemCommandGetLogLevels' + - $ref: '#/components/schemas/SystemCommandGetLogLevelNames' + - $ref: '#/components/schemas/SystemCommandGetSubsystemNames' + responses: + 200: + description: Successful command execution + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SystemGetLogLevelsResult' + - $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult' + - $ref: '#/components/schemas/SystemGetSubSystemNamesResult' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + get: + tags: + - System Commands + summary: Retrieve different values from the running service. + operationId: getSystemCommand + parameters: + - in: query + description: Get a value + name: command + schema: + type: string + enum: + - info + required: true + + responses: + 200: + description: Successful command execution + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SystemInfoResults' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' diff --git a/.gitbook/assets/owprov.yaml b/.gitbook/assets/owprov.yaml index 7f55715..f1ba029 100644 --- a/.gitbook/assets/owprov.yaml +++ b/.gitbook/assets/owprov.yaml @@ -181,6 +181,28 @@ components: items: $ref: '#/components/schemas/ManagementPolicy' + DeviceRules: + type: object + properties: + rcOnly: + type: string + enum: + - yes + - no + - inherit + rrm: + type: string + enum: + - yes + - no + - inherit + firmwareUpgrade: + type: string + enum: + - yes + - no + - inherit + # uuids: ent: Entity: type: object @@ -255,14 +277,19 @@ components: items: type: string format: uuid - rrm: - type: string - enum: - - off - - on - - inherit + deviceRules: + $ref: '#/components/schemas/DeviceRules' sourceIP: $ref: '#/components/schemas/StringList' + defaultEntity: + type: boolean + default: false + type: + type: string + enum: + - normal + - subscriber + default: normal EntityList: type: object @@ -327,12 +354,8 @@ components: location: type: string format: uuid - rrm: - type: string - enum: - - off - - on - - inherit + deviceRules: + $ref: '#/components/schemas/DeviceRules' sourceIP: $ref: '#/components/schemas/StringList' managementPolicies: @@ -365,6 +388,12 @@ components: items: type: string format: uuid + boards: + description: The list of OWAnalytics Boards created for this venue + type: array + items: + type: string + format: uuid VenueList: type: object @@ -481,6 +510,98 @@ components: items: $ref: '#/components/schemas/Location' + OperatorLocation: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + type: + type: string + enum: + - SERVICE + - EQUIPMENT + - AUTO + - MANUAL + - SPECIAL + - UNKNOWN + - CORPORATE + buildingName: + type: string + addressLines: + type: array + items: + type: string + city: + type: string + state: + type: string + postal: + type: string + country: + type: string + phones: + type: array + items: + type: string + mobiles: + type: array + items: + type: string + operatorId: + type: string + format: uuid + subscriberDeviceId: + type: string + format: uuid + geoCode: + type: string + + OperatorLocationList: + type: object + properties: + locations: + type: array + items: + $ref: '#/components/schemas/OperatorLocation' + + SubLocation: + type: object + properties: + type: + type: string + enum: + - SERVICE + - EQUIPMENT + - AUTO + - MANUAL + - SPECIAL + - UNKNOWN + - CORPORATE + buildingName: + type: string + addressLines: + type: array + items: + type: string + city: + type: string + state: + type: string + postal: + type: string + country: + type: string + phones: + type: array + items: + type: string + mobiles: + type: array + items: + type: string + geoCode: + type: string + # uuids: con: Contact: type: object @@ -544,6 +665,104 @@ components: items: $ref: '#/components/schemas/Contact' + OperatorContact: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + type: + type: string + enum: + - SUBSCRIBER + - USER + - INSTALLER + - CSR + - MANAGER + - BUSINESSOWNER + - TECHNICIAN + - CORPORATE + title: + type: string + salutation: + type: string + firstname: + type: string + lastname: + type: string + initials: + type: string + visual: + type: string + phones: + type: array + items: + type: string + mobiles: + type: array + items: + type: string + primaryEmail: + type: string + secondaryEmail: + type: string + accessPIN: + type: string + operatorId: + type: string + format: uuid + subscriberDeviceId: + type: string + format: uuid + + OperatorContactList: + type: object + properties: + contacts: + type: array + items: + $ref: '#/components/schemas/OperatorContact' + + SubContact: + type: object + properties: + type: + type: string + enum: + - SUBSCRIBER + - USER + - INSTALLER + - CSR + - MANAGER + - BUSINESSOWNER + - TECHNICIAN + - CORPORATE + title: + type: string + salutation: + type: string + firstname: + type: string + lastname: + type: string + initials: + type: string + visual: + type: string + phones: + type: array + items: + type: string + mobiles: + type: array + items: + type: string + primaryEmail: + type: string + secondaryEmail: + type: string + accessPIN: + type: string + DeviceConfigurationElement: type: object properties: @@ -585,17 +804,8 @@ components: subscriberOnly: type: boolean default: false - rrm: - type: string - enum: - - off - - on - - inherit - firmwareUpgrade: - type: string - example: auto or a time string of the format DOW-HH:MM - firmwareRCOnly: - type: boolean + deviceRules: + $ref: '#/components/schemas/DeviceRules' venue: type: string format: uuid @@ -645,12 +855,8 @@ components: deviceConfiguration: type: string format: uuid - rrm: - type: string - enum: - - off - - on - - inherit + deviceRules: + $ref: '#/components/schemas/DeviceRules' managementPolicy: type: string format: uuid @@ -668,6 +874,21 @@ components: minLength: 2 maxLength: 2 + VenueDeviceList: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + devices: + type: array + items: + type: string + InventoryTagList: type: object properties: @@ -828,6 +1049,9 @@ components: userId: type: string format: uuid + operatorId: + type: string + format: uuid macAddress: type: string serialNumber: @@ -846,6 +1070,10 @@ components: statusCode: type: integer format: int64 + registrationId: + type: string + minLength: 4 + maxLength: 16 Variable: type: object @@ -910,6 +1138,146 @@ components: items: $ref: '#/components/schemas/VariableBlock' + ServiceClass: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + operatorId: + type: string + format: uuid + cost: + type: number + currency: + type: string + minLength: 3 + maxLength: 3 + managementPolicy: + type: string + format: uuid + period: + type: string + enum: + - hourly + - daily + - monthly + - yearly + - quarterly + - lifetime + - custom1 + - custom2 + - custom3 + - custom4 + default: monthly + billingCode: + type: string + variables: + type: array + items: + $ref: '#/components/schemas/Variable' + defaultService: + type: boolean + default: false + + ServiceClassList: + type: object + properties: + serviceClasses: + type: array + items: + $ref: '#/components/schemas/ServiceClass' + + Operator: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + variables: + type: array + items: + $ref: '#/components/schemas/Variable' + defaultOperator: + type: boolean + default: false + deviceRules: + $ref: '#/components/schemas/DeviceRules' + managementPolicy: + type: string + format: uuid + managementRoles: + $ref: '#/components/schemas/ManagementRoleList' + sourceIP: + $ref: '#/components/schemas/StringList' + registrationId: + type: string + minLength: 4 + maxLength: 16 + + OperatorList: + type: object + properties: + operators: + type: array + items: + $ref: '#/components/schemas/Operator' + + SubscriberDevice: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + serialNumber: + type: string + realMacAddress: + type: string + operatorId: + type: string + format: uuid + deviceType: + type: string + subscriberId: + type: string + format: uuid + qrCode: + type: string + geoCode: + type: string + location: + $ref: '#/components/schemas/SubLocation' + contact: + $ref: '#/components/schemas/SubContact' + deviceRules: + $ref: '#/components/schemas/DeviceRules' + state: + type: string + locale: + type: string + minLength: 2 + maxLength: 2 + managementPolicy: + type: string + format: uuid + suspended: + type: boolean + default: false + configuration: + type: array + items: + $ref: '#/components/schemas/DeviceConfigurationElement' + serviceClass: + type: string + format: uuid + billingCode: + type: string + + SubscriberDeviceList: + type: object + properties: + subscriberDevices: + type: array + items: + $ref: '#/components/schemas/SubscriberDevice' + ######################################################################################### ## ## These are endpoints that all services in the OPenWiFI stack must provide @@ -1154,7 +1522,8 @@ paths: oneOf: - $ref: '#/components/schemas/EntityList' - $ref: '#/components/schemas/CountAnswer' - + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1174,15 +1543,15 @@ paths: format: uuid example: When looking for the root entity, the uuid 0000-0000-0000 must be entered. required: true - responses: 200: $ref: '#/components/schemas/Entity' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Entities @@ -1202,15 +1571,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Entity' - responses: 200: $ref: '#/components/schemas/Entity' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Entities @@ -1230,15 +1599,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Entity' - responses: 200: $ref: '#/components/schemas/Entity' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Entities @@ -1252,10 +1621,11 @@ paths: format: uuid example: The root entity cannot be deleted. required: true - responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1317,7 +1687,6 @@ paths: type: string format: uuid required: false - responses: 200: description: Return a list of contacts @@ -1327,6 +1696,8 @@ paths: oneOf: - $ref: '#/components/schemas/ContactList' - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1360,11 +1731,12 @@ paths: oneOf: - $ref: '#/components/schemas/Contact' - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Contacts @@ -1383,15 +1755,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Contact' - responses: 200: $ref: '#/components/schemas/Contact' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Contacts @@ -1410,15 +1782,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Contact' - responses: 200: $ref: '#/components/schemas/Contact' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Contacts @@ -1436,10 +1808,11 @@ paths: schema: type: boolean required: true - responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1489,7 +1862,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Return a list of Locations @@ -1499,6 +1871,8 @@ paths: oneOf: - $ref: '#/components/schemas/LocationList' - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1522,7 +1896,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Success @@ -1532,11 +1905,12 @@ paths: oneOf: - $ref: '#/components/schemas/Location' - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Locations @@ -1555,15 +1929,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Location' - responses: 200: $ref: '#/components/schemas/Location' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Locations @@ -1582,15 +1956,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Location' - responses: 200: $ref: '#/components/schemas/Location' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Locations @@ -1608,10 +1982,11 @@ paths: schema: type: boolean required: true - responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1696,6 +2071,13 @@ paths: type: string example: serialNumber:a,created:d required: false + - in: query + description: return extended information + name: orderSpec + schema: + type: boolean + default: false + required: false - in: query description: return the list of devices under RRM name: rrmOnly @@ -1720,6 +2102,7 @@ paths: - $ref: '#/components/schemas/SerialNumberList' - $ref: '#/components/schemas/InventoryTagList' - $ref: '#/components/schemas/CountAnswer' + - $ref: '#/components/schemas/StringList' 400: $ref: '#/components/responses/BadRequest' 403: @@ -1760,6 +2143,12 @@ paths: schema: type: boolean required: false + - in: query + name: subscriberEntity + schema: + type: string + format: uuid + required: false responses: 200: description: Succesful retrieve configuratiopn or part of the configuration @@ -1797,11 +2186,12 @@ paths: responses: 200: $ref: '#/components/schemas/InventoryTag' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Inventory @@ -1819,7 +2209,7 @@ paths: schema: type: boolean required: false - - in: path + - in: query name: removeSubscriber schema: type: string @@ -1840,11 +2230,12 @@ paths: application/json: schema: $ref: '#/components/schemas/InventoryTag' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Inventory @@ -1861,6 +2252,8 @@ paths: responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1932,7 +2325,20 @@ paths: schema: type: boolean required: false - + - in: query + description: return the devices under a venue + name: getDevices + schema: + type: boolean + default: false + required: false + - in: query + description: return the devices under a venue and its children. Must select getDevices=true as well. + name: getChildren + schema: + type: boolean + default: false + required: false responses: 200: description: Return a list of venues. @@ -1942,6 +2348,9 @@ paths: oneOf: - $ref: '#/components/schemas/VenueList' - $ref: '#/components/schemas/CountAnswer' + - $ref: '#/components/schemas/VenueDeviceList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -1968,7 +2377,6 @@ paths: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Venues @@ -2013,7 +2421,6 @@ paths: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Venues @@ -2026,6 +2433,30 @@ paths: type: string format: uuid required: true + - in: query + name: updateAllDevices + schema: + type: boolean + default: false + required: false + - in: query + name: rebootAllDevices + schema: + type: boolean + default: false + required: false + - in: query + name: testUpdateOnly + schema: + type: boolean + default: false + required: false + - in: query + name: upgradeAllDevices + schema: + type: boolean + default: false + required: false requestBody: description: Information used to modify the new venue content: @@ -2035,12 +2466,19 @@ paths: responses: 200: - $ref: '#/components/schemas/Venue' + description: Return venue information or list of serial number updated + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Venue' + - $ref: '#/components/schemas/SerialNumberList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Venues @@ -2054,10 +2492,11 @@ paths: format: uuid example: The root entity cannot be deleted. required: true - responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2100,7 +2539,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Return a list of Venues @@ -2108,6 +2546,8 @@ paths: application/json: schema: $ref: '#/components/schemas/MapList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2126,7 +2566,6 @@ paths: type: string format: uuid required: true - responses: 200: description: Successfull retrieval of a map @@ -2134,11 +2573,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Map' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Maps @@ -2157,7 +2597,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Map' - responses: 200: $ref: '#/components/schemas/Map' @@ -2165,7 +2604,6 @@ paths: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Maps @@ -2184,15 +2622,15 @@ paths: application/json: schema: $ref: '#/components/schemas/Map' - responses: 200: $ref: '#/components/schemas/ManagementPolicy' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Maps @@ -2208,6 +2646,8 @@ paths: responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2268,7 +2708,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Return a list of Venues @@ -2278,6 +2717,8 @@ paths: oneOf: - $ref: '#/components/schemas/ManagementPolicyList' - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2301,7 +2742,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Succesful retrieve a management policy @@ -2311,11 +2751,12 @@ paths: oneOf: - $ref: '#/components/schemas/ManagementPolicy' - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Management Policies @@ -2334,15 +2775,15 @@ paths: application/json: schema: $ref: '#/components/schemas/ManagementPolicy' - responses: 200: $ref: '#/components/schemas/ManagementPolicy' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Management Policies @@ -2361,15 +2802,15 @@ paths: application/json: schema: $ref: '#/components/schemas/ManagementPolicy' - responses: 200: $ref: '#/components/schemas/ManagementPolicy' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Management Policies @@ -2383,10 +2824,11 @@ paths: format: uuid example: The root entity cannot be deleted. required: true - responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2436,7 +2878,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Return a list of elements @@ -2446,6 +2887,8 @@ paths: oneOf: - $ref: '#/components/schemas/ManagementRoleList' - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2478,6 +2921,8 @@ paths: oneOf: - $ref: '#/components/schemas/ManagementRole' - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2505,11 +2950,12 @@ paths: responses: 200: $ref: '#/components/schemas/ManagementRole' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Management Roles @@ -2528,10 +2974,11 @@ paths: application/json: schema: $ref: '#/components/schemas/ManagementRole' - responses: 200: $ref: '#/components/schemas/ManagementRole' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2551,12 +2998,14 @@ paths: responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - /configurations: + /configuration: get: tags: - Configurations @@ -2606,7 +3055,6 @@ paths: type: string format: uuid required: false - responses: 200: description: Return a list of elements @@ -2616,13 +3064,14 @@ paths: oneOf: - $ref: '#/components/schemas/DeviceConfigurationList' - $ref: '#/components/schemas/CountAnswer' - + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - /configurations/{uuid}: + /configuration/{uuid}: get: tags: - Configurations @@ -2641,7 +3090,6 @@ paths: schema: type: boolean required: false - responses: 200: description: Success @@ -2651,11 +3099,12 @@ paths: oneOf: - $ref: '#/components/schemas/DeviceConfiguration' - $ref: '#/components/schemas/ExpandedUseEntryMapList' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Configurations @@ -2680,15 +3129,15 @@ paths: application/json: schema: $ref: '#/components/schemas/DeviceConfiguration' - responses: 200: $ref: '#/components/schemas/DeviceConfiguration' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Configurations @@ -2708,15 +3157,15 @@ paths: application/json: schema: $ref: '#/components/schemas/DeviceConfiguration' - responses: 200: $ref: '#/components/schemas/DeviceConfiguration' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Configurations @@ -2730,10 +3179,11 @@ paths: format: uuid example: The root entity cannot be deleted. required: true - responses: 204: $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2767,6 +3217,8 @@ paths: type: array items: type: string + 400: + $ref: '#/components/responses/BadRequest' 403: $ref: '#/components/responses/Unauthorized' 404: @@ -2822,7 +3274,6 @@ paths: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - delete: tags: - Subscriber Registration @@ -2860,7 +3311,6 @@ paths: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - post: tags: - Subscriber Registration @@ -2883,6 +3333,11 @@ paths: schema: type: string required: false + - in: query + name: registrationId + schema: + type: string + required: true responses: 200: $ref: '#/components/schemas/SignupEntry' @@ -2892,7 +3347,6 @@ paths: $ref: '#/components/responses/Unauthorized' 404: $ref: '#/components/responses/NotFound' - put: tags: - Subscriber Registration @@ -2931,7 +3385,6 @@ paths: status: type: string required: false - responses: 200: $ref: '#/components/schemas/SignupEntry' @@ -2942,7 +3395,7 @@ paths: 404: $ref: '#/components/responses/NotFound' - /variables: + /variable: get: tags: - Variable Configuration Blocks @@ -3002,6 +3455,815 @@ paths: 404: $ref: '#/components/responses/NotFound' + /operator: + get: + operationId: getOperators + tags: + - Operators + summary: Retrieve the list of currently configured operators + parameters: + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of operators comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of operators + name: countOnly + schema: + type: boolean + required: false + responses: + 200: + description: Successfully retrieved operator list + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/OperatorList' + - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /operator/{uuid}: + get: + operationId: getOperator + tags: + - Operators + summary: Retrieve an operator + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/schemas/Operator' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + operationId: deleteOperator + tags: + - Operators + summary: Delete an operator + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + summary: Create a new operator + operationId: createOperator + tags: + - Operators + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: + should be set to 0 when creating a new operator + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Operator' + responses: + 200: + $ref: '#/components/schemas/Operator' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + put: + summary: Update an existing operator + operationId: updateOperator + tags: + - Operators + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Operator' + responses: + 200: + $ref: '#/components/schemas/Operator' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /serviceClass: + get: + operationId: getServiceClasses + tags: + - ServiceClass + summary: Retrieve the list of currently configured service class + parameters: + - in: query + description: The operator + name: operatorId + schema: + type: string + format: uuid + required: true + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of operators comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of operators + name: countOnly + schema: + type: boolean + required: false + responses: + 200: + description: Successfully retrieved operator list + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ServiceClassList' + - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /serviceClass/{uuid}: + get: + operationId: getServiceClass + tags: + - ServiceClass + summary: Retrieve a service class + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/schemas/ServiceClass' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + operationId: deleteServiceClass + tags: + - ServiceClass + summary: Delete a service class + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + summary: Create a service class + tags: + - ServiceClass + operationId: createServiceClass + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: + should be set to 0 when creating a new operator + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceClass' + responses: + 200: + $ref: '#/components/schemas/ServiceClass' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + put: + summary: Update a service class + tags: + - ServiceClass + operationId: updateServiceClass + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceClass' + responses: + 200: + $ref: '#/components/schemas/ServiceClass' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /subscriberDevice: + get: + operationId: getsubscriberDevices + tags: + - Subscriber Devices + summary: Retrieve the list of subscriber devices + parameters: + - in: query + description: The operator + name: operatorId + schema: + type: string + format: uuid + required: true + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of operators comma separated + name: select + schema: + type: string + example: serial1,serial2,serial3 + required: false + - in: query + description: return the number of operators + name: countOnly + schema: + type: boolean + required: false + responses: + 200: + description: list of subscriber devices + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/SubscriberDeviceList' + - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /subscriberDevice/{uuid}: + get: + operationId: getSubscriberDevice + tags: + - Subscriber Devices + summary: Retrieve a subscriber device + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/schemas/SubscriberDevice' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + operationId: deleteSubscriberDevice + tags: + - Subscriber Devices + summary: Delete a subscriber device + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + summary: Create a subscriber device + tags: + - Subscriber Devices + operationId: createSubscriberDevice + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + example: + should be set to 0 when creating a new operator + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SubscriberDevice' + responses: + 200: + $ref: '#/components/schemas/SubscriberDevice' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + put: + summary: Update a subscriber device + tags: + - Subscriber Devices + operationId: updateSubscriberDevice + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SubscriberDevice' + responses: + 200: + $ref: '#/components/schemas/SubscriberDevice' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /operatorLocation: + get: + tags: + - Operator Locations + operationId: getOperatorLocations + summary: Retrieve a list of locations. + parameters: + - in: query + name: operatorId + schema: + type: string + format: uuid + required: true + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of Locations comma separated + name: select + schema: + type: string + example: uuid1,uuid2,uuid3 + required: false + - in: query + description: return the number of Locations + name: countOnly + schema: + type: boolean + required: false + - in: query + description: return only the UUIDs of Locations + name: uuidOnly + schema: + type: boolean + required: false + responses: + 200: + description: Return a list of Locations + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/OperatorLocationList' + - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /operatorLocation/{uuid}: + get: + tags: + - Operator Locations + operationId: getOperatorLocation + summary: Retrieve a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/schemas/OperatorLocation' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + tags: + - Operator Locations + operationId: createOperatorLocation + summary: Create a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new location + content: + application/json: + schema: + $ref: '#/components/schemas/OperatorLocation' + responses: + 200: + $ref: '#/components/schemas/OperatorLocation' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + put: + tags: + - Operator Locations + operationId: modifyOperatorLocation + summary: Modify a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify the new location + content: + application/json: + schema: + $ref: '#/components/schemas/OperatorLocation' + responses: + 200: + $ref: '#/components/schemas/OperatorLocation' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + tags: + - Operator Locations + operationId: deleteOperatorLocation + summary: Delete a specific location. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: force + schema: + type: boolean + required: true + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /operatorContact: + get: + tags: + - Operator Contacts + operationId: getOperatorContacts + summary: Retrieve a list of operator contacts. + parameters: + - in: query + name: operatorId + schema: + type: string + format: uuid + required: true + - in: query + description: Pagination start (starts at 1. If not specified, 1 is assumed) + name: offset + schema: + type: integer + required: false + - in: query + description: Maximum number of entries to return (if absent, no limit is assumed) + name: limit + schema: + type: integer + required: false + - in: query + description: Filter the results + name: filter + schema: + type: string + required: false + - in: query + description: Supply a list of operator contacts comma separated + name: select + schema: + type: string + example: uuid1,uuid2,uuid3 + required: false + - in: query + description: return the number of operator contacts + name: countOnly + schema: + type: boolean + required: false + - in: query + description: return only the UUIDs of operator contacts + name: uuidOnly + schema: + type: boolean + required: false + responses: + 200: + description: Return a list of operator contacts + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/OperatorContactList' + - $ref: '#/components/schemas/CountAnswer' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /operatorContact/{uuid}: + get: + tags: + - Operator Contacts + operationId: getOperatorContact + summary: Retrieve a specific operator contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + responses: + 200: + $ref: '#/components/schemas/OperatorContact' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: + tags: + - Operator Contacts + operationId: createOperatorContact + summary: Create a specific operator contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to create the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/OperatorContact' + responses: + 200: + $ref: '#/components/schemas/OperatorContact' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + put: + tags: + - Operator Contacts + operationId: modifyOperatorContact + summary: Modify a specific operator contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + requestBody: + description: Information used to modify the new entity + content: + application/json: + schema: + $ref: '#/components/schemas/OperatorContact' + responses: + 200: + $ref: '#/components/schemas/OperatorContact' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + delete: + tags: + - Operator Contacts + operationId: deleteOperatorContact + summary: Delete a specific operator contact. + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + required: true + - in: query + name: force + schema: + type: boolean + required: true + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + ######################################################################################### ## ## These are endpoints that all services in the OpenWiFi stack must provide @@ -3066,7 +4328,6 @@ paths: enum: - info required: true - responses: 200: description: Successful command execution diff --git a/SUMMARY.md b/SUMMARY.md index 9cda88a..09c4538 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -8,8 +8,8 @@ * [About the OpenWiFi SDK](about-openwifi/about-the-sdk.md) * [OpenWiFi Firmware](about-openwifi/firmware.md) * [About Device Provisioning](about-openwifi/device-provisioning.md) - + [Supported Hardware](about-openwifi/supported-hardware.md) - + [Integrations](about-openwifi/openwifi-stack.md) + * [Supported Hardware](about-openwifi/supported-hardware.md) + * [Integrations](about-openwifi/openwifi-stack.md) * [Ordering OpenWiFi APs](ordering-open-wi-fi-aps.md) * [Device Partner Information](device-partner-information.md) * [Cloud Partner Information](cloud-partner-information.md) @@ -35,6 +35,7 @@ * [Gateway Service](api/gateway-service.md) * [Firmware Management Service](api/firmware-management-service.md) * [Provisioning Service](api/provisioning-service.md) + * [Analytics Service](api/analytics-service.md) * [Monitoring](monitoring/README.md) * [ELK Integration](monitoring/elk-integration.md) diff --git a/api/analytics-service.md b/api/analytics-service.md new file mode 100644 index 0000000..3e85ecf --- /dev/null +++ b/api/analytics-service.md @@ -0,0 +1,5 @@ +# Analytics Service + +{% swagger src="../.gitbook/assets/owanalytics.yaml" path="undefined" method="undefined" %} +[owanalytics.yaml](../.gitbook/assets/owanalytics.yaml) +{% endswagger %} diff --git a/api/provisioning-service.md b/api/provisioning-service.md index c9b0988..1ab87b7 100644 --- a/api/provisioning-service.md +++ b/api/provisioning-service.md @@ -1,213 +1,209 @@ # Provisioning Service -{% swagger src="../.gitbook/assets/owprov.yaml" path="undefined" method="undefined" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) -{% endswagger %} - {% swagger src="../.gitbook/assets/owprov.yaml" path="/entity/{uuid}" method="get" %} [owprov.yaml](../.gitbook/assets/owprov.yaml) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/entity/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/entity/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/entity/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/entity/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/entity/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/entity/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/contact" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/contact" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/contact/{uuid}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/contact/{uuid}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/contact/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/contact/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/contact/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/contact/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/contact/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/contact/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/location" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/location" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/location/{uuid}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/location/{uuid}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/location/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/location/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/location/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/location/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/location/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/location/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/inventory" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/inventory" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/inventory/{serialNumber}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/inventory/{serialNumber}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/inventory/{serialNumber}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/inventory/{serialNumber}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/inventory/{serialNumber}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/inventory/{serialNumber}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/inventory/{serialNumber}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/inventory/{serialNumber}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/venue" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/venue" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/venue/{uuid}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/venue/{uuid}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/venue/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/venue/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/venue/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/venue/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/venue/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/venue/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/map" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/map" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/map/{uuid}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/map/{uuid}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/map/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/map/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/map/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/map/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/map/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/map/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementPolicy" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementPolicy" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementPolicy/{uuid}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementPolicy/{uuid}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementPolicy/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementPolicy/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementPolicy/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementPolicy/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementPolicy/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementPolicy/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementRole" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementRole" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementRole/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementRole/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementRole/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementRole/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/managementRole/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/managementRole/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/configurations" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/configurations" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/configurations/{uuid}" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/configurations/{uuid}" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/configurations/{uuid}" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/configurations/{uuid}" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/configurations/{uuid}" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/configurations/{uuid}" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/configurations/{uuid}" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/configurations/{uuid}" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/iptocountry" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/iptocountry" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/signup" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/signup" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/signup" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/signup" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/signup" method="put" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/signup" method="put" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/signup" method="delete" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/signup" method="delete" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/variables" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/variables" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/dashboard" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/dashboard" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/system" method="get" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/system" method="get" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} -{% swagger src="../.gitbook/assets/owprov.yaml" path="/system" method="post" %} -[owprov.yaml](../.gitbook/assets/owprov.yaml) +{% swagger src="../.gitbook/assets/owprov (1).yaml" path="/system" method="post" %} +[owprov (1).yaml](<../.gitbook/assets/owprov (1).yaml>) {% endswagger %} diff --git a/configuration-examples/device-feature-configuration-examples/expresswifi.md b/configuration-examples/device-feature-configuration-examples/expresswifi.md index 6451a10..607e06c 100644 --- a/configuration-examples/device-feature-configuration-examples/expresswifi.md +++ b/configuration-examples/device-feature-configuration-examples/expresswifi.md @@ -10,7 +10,7 @@ Express Wi-Fi partners with service providers to deliver great wi-fi to people w For information about becoming an expressWIFI partner please visit their [site.](https://expresswifi.fb.com) -![](<../../.gitbook/assets/image (36).png>) +![](<../../.gitbook/assets/image (40).png>) ## Configuration diff --git a/getting-started/access-points/README.md b/getting-started/access-points/README.md index 6fffd5b..5d50eea 100644 --- a/getting-started/access-points/README.md +++ b/getting-started/access-points/README.md @@ -10,7 +10,7 @@ Given many cloud and ODM partners wish to consume the 2.0 reference stack early, ## Device Interactions with SDK -![OpenWiFi with uCentral Management](<../../.gitbook/assets/image (22) (2).png>) +![OpenWiFi with uCentral Management](<../../.gitbook/assets/image (22) (1).png>) OpenWiFi 2.0 follows the uCentral system. Complete data model is available [here](http://ucentral.io/docs/ucentral-schema.html). Upon discovery of the cloud, a device default or specific configuration is transferred. diff --git a/getting-started/access-points/local-device-settings.md b/getting-started/access-points/local-device-settings.md index d112d5d..468d288 100644 --- a/getting-started/access-points/local-device-settings.md +++ b/getting-started/access-points/local-device-settings.md @@ -15,43 +15,43 @@ Association with and logging in to the device will permit initial WAN connectivi ## Using Maverick -![Maverick Login Page](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.04.23 PM.png>) +![Maverick Login Page](../../.gitbook/assets/screen-shot-2021-07-29-at-5.04.23-pm.png) After association to the Maverick SSID, open a web browser to `http://192.168.1.1`\ Log into the OpenWiFi device with username: **`root`** and password: **`openwifi`** -![Logged into Maverick](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.06.35 PM.png>) +![Logged into Maverick](../../.gitbook/assets/screen-shot-2021-07-29-at-5.06.35-pm.png) When the page above is displayed, begin to configure Uplink based on the WAN requirements of the deployment. -![Uplink Configuration in Maverick](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.07.50 PM.png>) +![Uplink Configuration in Maverick](../../.gitbook/assets/screen-shot-2021-07-29-at-5.07.50-pm.png) If connection uses Point to Point over Ethernet (PPPoE) username and password credentials, enter those values and save. -![PPPoE Uplink](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.09.14 PM.png>) +![PPPoE Uplink](../../.gitbook/assets/screen-shot-2021-07-29-at-5.09.14-pm.png) If the OpenWiFi device has a Cellular connection which is possible on device models with 4G and 5G radios, the network Access Point Name (APN) and PIN will be required. These values are supplied by your mobile network provider. -![Cellular Uplink](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.11.05 PM.png>) +![Cellular Uplink](../../.gitbook/assets/screen-shot-2021-07-29-at-5.11.05-pm.png) When dynamic address allocation is not available, static IP address assignment may be required. IPv4 and IPv6 are supported, enter these values with DNS address and save. -![Uplink Static IP](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.12.39 PM.png>) +![Uplink Static IP](../../.gitbook/assets/screen-shot-2021-07-29-at-5.12.39-pm.png) Otherwise leave the Uplink configuration to DHCP or cloud defaults. -![Uplink DHCP](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.13.40 PM.png>) +![Uplink DHCP](../../.gitbook/assets/screen-shot-2021-07-29-at-5.13.40-pm.png) ## Manual Redirector and Certificate Upload If under rare circumstances it is not possible to discover the OpenWiFi cloud associated with the device or there is a need to replace device certificates, this may be configured in Settings. -![Local Redirector Setting](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.16.01 PM.png>) +![Local Redirector Setting](../../.gitbook/assets/screen-shot-2021-07-29-at-5.16.01-pm.png) ## System It is possible to reset the device to defaults, or locally update firmware using the commands available from System. -![System Commands](<../../.gitbook/assets/Screen Shot 2021-07-29 at 5.17.13 PM.png>) +![System Commands](../../.gitbook/assets/screen-shot-2021-07-29-at-5.17.13-pm.png) \*\*\*\* diff --git a/monitoring/elk-integration.md b/monitoring/elk-integration.md index 37247f3..ef2512f 100644 --- a/monitoring/elk-integration.md +++ b/monitoring/elk-integration.md @@ -6,7 +6,7 @@ description: Kafka integration with ELK The following pipeline is used to leverage Kafka messages being emitted from OpenWiFi 2.0 for ELK (Elastic Logstash Kibana) stack integration : -![](../.gitbook/assets/kafka-ELK-pipeline.png) +![](../.gitbook/assets/kafka-elk-pipeline.png) TIP OpenWiFi project has deployed an ELK stack for community members to access [here](https://kibana.lab.wlan.tip.build). diff --git a/provisioning/README.md b/provisioning/README.md index 17c0164..355ef59 100644 --- a/provisioning/README.md +++ b/provisioning/README.md @@ -26,7 +26,7 @@ Upon successful connection the device exchanges its capabilities with the OpenWi Within OpenWiFi devices, the uCentral agent has a reader and renderer process providing serialization and validation of data sent from cloud.\ If any data presented can not be processed by the local agent, this is returned within an ERROR message using the same websocket connection. -![High Level SDK Gateway to uCentral Agent](<../.gitbook/assets/image (30) (1).png>) +![High Level SDK Gateway to uCentral Agent](<../.gitbook/assets/image (22) (1) (1).png>) If the device agrees with provisioning information presented, the render process builds calls into the operating system configuration sub-system known as UCI. The Unified Configuration Interface ensures OpenWrt compliant syntax is persisted within the device. diff --git a/provisioning/data-model-introduction.md b/provisioning/data-model-introduction.md index 3eb207d..f1c83d7 100644 --- a/provisioning/data-model-introduction.md +++ b/provisioning/data-model-introduction.md @@ -16,7 +16,7 @@ The complete data model may be found here : [https://ucentral.io/docs/ucentral-s Each device has a Universally Unique Identifier (UUID). For each device, the configuration presented either manually, via the future Provisioning service from OpenWifi or via a commercial controller generation of provisioning data, the high level relationships of the schema may be understood as follows. -![uCentral Agent Schema Processing](<../.gitbook/assets/image (32).png>) +![uCentral Agent Schema Processing](<../.gitbook/assets/image (37).png>) The unique device record has a set of top level configurations. A device is referred to as a 'unit' that may have a Description, Location, TimeZone as example. Each unit may have globals for IPv4 and IPv6 networks that are derived to lower lever interfaces in later generation. diff --git a/user-interface/README.md b/user-interface/README.md index 7129196..0a9bd1a 100644 --- a/user-interface/README.md +++ b/user-interface/README.md @@ -8,7 +8,7 @@ Release 2.0 uses a Single-Page Application (SPA) as an example user interface bu ## Login to OpenWiFi SDK -![Login Page](<../.gitbook/assets/Screen Shot 2021-07-28 at 4.40.17 PM.png>) +![Login Page](../.gitbook/assets/screen-shot-2021-07-28-at-4.40.17-pm.png) Default username is: **`tip@ucentral.com`** and password is: **`openwifi`** @@ -16,19 +16,19 @@ Default username is: **`tip@ucentral.com`** and password is: **`openwifi`** A left side navigation menu provides direction to major feature or service settings. -![Left Navigation](<../.gitbook/assets/Screen Shot 2021-07-29 at 3.21.37 PM.png>) +![Left Navigation](../.gitbook/assets/screen-shot-2021-07-29-at-3.21.37-pm.png) ## Internationalization OpenWiFi 2.0 SDK supports multiple languages. Simply select the desired language from the right drop down for pages to re-populate accordingly. -![](<../.gitbook/assets/Screen Shot 2021-07-29 at 3.26.35 PM.png>) +![](../.gitbook/assets/screen-shot-2021-07-29-at-3.26.35-pm.png) ## Devices Upon login the first page presented is a Devices table. This table reflects all discovered and managed devices known by the OpenWiFi SDK. -![Devices Table](<../.gitbook/assets/Screen Shot 2021-08-01 at 12.04.01 PM.png>) +![Devices Table](../.gitbook/assets/screen-shot-2021-08-01-at-12.04.01-pm.png) Devices table indicates device Connected or Disconnected state in the first column with green and red respectively. @@ -44,13 +44,13 @@ Three final columns provide Details (also obtained by selecting the serial numbe From the Devices table, second from right column icon the WiFi Analysis may be accessed. This may also be accessed within the Device View page of a single record along the top right of Statistics section. -![Wi-Fi Analysis](<../.gitbook/assets/Screen Shot 2021-08-01 at 12.04.36 PM.png>) +![Wi-Fi Analysis](../.gitbook/assets/screen-shot-2021-08-01-at-12.04.36-pm.png) Within the WiFi Analysis page, all active associations are displayed with the ability to view approximately the last 30 minutes of data reported from the Access Point. For each association the device MAC address, mode of connection and SSID are displayed. This will include end devices as well as Wi-Fi infrastructure such as WDS and Mesh associations. -![](<../.gitbook/assets/Screen Shot 2021-07-28 at 4.54.43 PM.png>) +![](../.gitbook/assets/screen-shot-2021-07-28-at-4.54.43-pm.png) Associations have RSSI, Rx Rate & Bytes, Tx Rate & Bytes, MCS negotiated, Number Spatial Streams and IP Address information. @@ -58,8 +58,8 @@ Associations have RSSI, Rx Rate & Bytes, Tx Rate & Bytes, MCS negotiated, Number OpenWiFi SDK provides visual indications on the overall health of the deployed Wi-Fi network. this includes Device Status for connected and non-connected devices. Device health indicating percentage of devices failing a health check. Distribution of devices by vendor in the network and by model. -![Dashboard View](<../.gitbook/assets/Screen Shot 2021-08-01 at 12.06.15 PM.png>) +![Dashboard View](../.gitbook/assets/screen-shot-2021-08-01-at-12.06.15-pm.png) Additionally, verified certificates or serial mismatch certificates, number of Command actions from all Gateways to devices and devices with greater than 75% memory utilization, greater than 50% less than 75% memory and less than 50% utilization are displayed. -![](<../.gitbook/assets/Screen Shot 2021-07-30 at 12.09.27 AM.png>) +![](../.gitbook/assets/screen-shot-2021-07-30-at-12.09.27-am.png) diff --git a/user-interface/devices-view/README.md b/user-interface/devices-view/README.md index 7cfeaa2..f722799 100644 --- a/user-interface/devices-view/README.md +++ b/user-interface/devices-view/README.md @@ -6,7 +6,7 @@ description: OpenWiFi 2.0 SDK Each device presents Metrics and Health check data to the Gateway. Devices view displays this information in the following organization: -* Status +* Status * Configuration * Logs * Health @@ -14,7 +14,7 @@ Each device presents Metrics and Health check data to the Gateway. Devices view * Statistics * Command History -![Initial Device View](<../../.gitbook/assets/Screen Shot 2021-07-28 at 5.15.03 PM.png>) +![Initial Device View](../../.gitbook/assets/screen-shot-2021-07-28-at-5.15.03-pm.png) ## Status @@ -23,7 +23,7 @@ Uptime and Last Contact reflect communication state.\ Load indicates processing load on the device.\ Memory Used indicates free memory on the device. -![Device Status](<../../.gitbook/assets/Screen Shot 2021-07-28 at 5.17.59 PM.png>) +![Device Status](../../.gitbook/assets/screen-shot-2021-07-28-at-5.17.59-pm.png) ## Configuration @@ -31,19 +31,19 @@ Device UUID, Serial Number, MAC Address and Device Type are displayed.\ Last configuration update date and timestamp reflects the last time a "configure" action completed on the device.\ Password may be set and device notes may be added. -![Device view Configuration Panel](<../../.gitbook/assets/Screen Shot 2021-07-28 at 5.21.07 PM.png>) +![Device view Configuration Panel](../../.gitbook/assets/screen-shot-2021-07-28-at-5.21.07-pm.png) ## Logs Log history of the device is presented within Logs. Expand the tile selecting the down arrow. -![](<../../.gitbook/assets/Screen Shot 2021-07-28 at 5.25.29 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-28-at-5.25.29-pm.png) ## Health Health score is an active tile reflecting the device health out of a score reported by the device to Gateway. Health metrics are configured on the device based on chosen data model options. When the device falls out of 100%, this tile changes to red. Expanding the tile will present all health reports. Those with less than 100% score will contain reasons for the result from this interface. -![](<../../.gitbook/assets/Screen Shot 2021-07-28 at 5.24.00 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-28-at-5.24.00-pm.png) ## Commands @@ -60,4 +60,4 @@ Commands tile provides a number of administrative actions for the user: | Factory Reset | Hard Reset remote device - destroys device local config | | Configure | Upload Device Configuration | -![Commands Tile](<../../.gitbook/assets/Screen Shot 2021-07-28 at 5.25.50 PM.png>) +![Commands Tile](../../.gitbook/assets/screen-shot-2021-07-28-at-5.25.50-pm.png) diff --git a/user-interface/devices-view/command-history.md b/user-interface/devices-view/command-history.md index 3455eca..9f36b50 100644 --- a/user-interface/devices-view/command-history.md +++ b/user-interface/devices-view/command-history.md @@ -6,20 +6,20 @@ description: OpenWiFi SDK 2.0 Multiple events are recorded in the Command History tile. Each line item will have a Result, Details, and Delete action. -![Command History Tile](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.10.22 PM.png>) +![Command History Tile](../../.gitbook/assets/screen-shot-2021-07-29-at-3.10.22-pm.png) When an rTTY session is executed, this is a displayed command history. Selecting the Result icons will display the Success or Fail of the command. -![rTTY Command History](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.12.02 PM.png>) +![rTTY Command History](../../.gitbook/assets/screen-shot-2021-07-29-at-3.12.02-pm.png) Each provisioning event is reflected as a configure command history. To see the entire JSON payload and the result, including success or error with message, simply select Details to expand the dialog below with this data. A date and time in the third column indicates when the configure command was executed successfully. -![Configure Command History](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.12.27 PM.png>) +![Configure Command History](../../.gitbook/assets/screen-shot-2021-07-29-at-3.12.27-pm.png) If a provisioning event has failed to complete, its command history for configure will show as pending. -![configure Pending Command History](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.18.12 PM.png>) +![configure Pending Command History](../../.gitbook/assets/screen-shot-2021-07-29-at-3.18.12-pm.png) Remote packet capture is shown as the trace command history. When packet captures are persisted in the OpenWiFi SDK, they may be downloaded again through the cloud download icon. -![trace Command History](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.16.52 PM.png>) +![trace Command History](../../.gitbook/assets/screen-shot-2021-07-29-at-3.16.52-pm.png) diff --git a/user-interface/devices-view/commands.md b/user-interface/devices-view/commands.md index 62e8d33..ad89f88 100644 --- a/user-interface/devices-view/commands.md +++ b/user-interface/devices-view/commands.md @@ -11,53 +11,53 @@ Each of these represent API calls exposed on the OpenAPI northbound interface fr Selecting the Reboot action will prompt the below dialog. Options presented permit an immediate reboot or a scheduled reboot based on date and time. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.25.03 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.25.03-pm.png) ## Firmware Upgrade Multiple methods exist to execute a remote Firmware Upgrade of a device. When selecting Firmware Upgrade via the Commands tile, a simple dialog to upgrade immediately or at a scheduled time is presented. Alternatively using the Firmware Management Service provides a complete solution including managed access to all TIP firmware images. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.28.44 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.28.44-pm.png) ## Wi-Fi Scan OpenWiFi devices may perform channel scanning and return this neighbor and RF data to the SDK in an on demand or ongoing manner. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.31.03 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.31.03-pm.png) ### Wi-Fi Scan Results Scan operations function over all channels. If 5GHz channels do not display in the returned results ( either via the UI or over API ) this indicates the device is configured in a DFS channel for which it may not return survey scans at this time. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.33.58 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.33.58-pm.png) ## Connect OpenWiFi enables remote connection to any managed device using rTTY encrypted shell session. Selecting Connect will cause a browser tab to open with the login session to current device. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.35.48 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.35.48-pm.png) ## Blink To assist with remote identification of devices in the network, it is possible to turn the LED lights On, Off, of continuous blinking. This may be run on-demand or scheduled. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.37.30 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.37.30-pm.png) ## Trace Trace feature enables a remote packet capture to occur on the managed device, over a specified period of time or amount of traffic, returning the "pcap" packet capture file locally to the OpenWiFi admin user. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.39.24 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.39.24-pm.png) Once complete the user is asked to open or save the packet capture file locally. -![](<../../.gitbook/assets/image (33).png>) +![](<../../.gitbook/assets/image (38).png>) ## Factory Reset It is possible to revert a device to initial out of box state from the OpenWiFi SDK. Sending a Factory Reset will remove all configuration on the device and optionally reset the discovered cloud stored as the 'Redirector' in the device configuration. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.46.29 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.46.29-pm.png) {% hint style="info" %} Note: When Redirector is not kept, devices will re-contact the Certificate Authority to re-discover their OpenWiFi cloud address @@ -67,4 +67,4 @@ Note: When Redirector is not kept, devices will re-contact the Certificate Autho Prior to the introduction of OpenWiFi 2.0 Provisioning Service, device configuration is done through creation of the JSON provisioning file and either loading that file or applying its contents using the dialog presented via Configure. The same options exist when using the API directly. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.48.31 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.48.31-pm.png) diff --git a/user-interface/devices-view/statistics.md b/user-interface/devices-view/statistics.md index d9b1b48..1f94007 100644 --- a/user-interface/devices-view/statistics.md +++ b/user-interface/devices-view/statistics.md @@ -6,15 +6,15 @@ description: OpenWiFi 2.0 SDK Each device page presents statistics in traffic terms per interface as a line graph of bandwidth over time. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.52.10 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.52.10-pm.png) The generated image may be downloaded for offline use. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.53.14 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.53.14-pm.png) Accessing Wi-Fi Analysis and Last Statistics may be found at the top right of Statistics tile. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.06.20 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-3.06.20-pm.png) ## Wi-Fi Analysis @@ -24,7 +24,7 @@ Viewing associations, from the Associations table, and their use is important in Each association is known by their MAC address or BSSID value. The mode of connection will indicate if an end user client device entering the "ap" or if a client is associated as "wds" or "mesh. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 2.57.34 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-2.57.34-pm.png) The access point view of RSSI, Rx and Tx Rate, Modulation Coding Scheme and Number of Spatial Streams are exposed for each association. @@ -34,4 +34,4 @@ Using the slider along the top, the last 15 to 30 minutes of performances data m The option to view Latest Statistics is at time of the MVP release, intended to help the Community see on a per device basis how much, or how little depending on device configuration, is being sent to the OpenWiFi Gateway in terms of telemetry. -![](<../../.gitbook/assets/Screen Shot 2021-07-29 at 3.04.42 PM.png>) +![](../../.gitbook/assets/screen-shot-2021-07-29-at-3.04.42-pm.png) diff --git a/user-interface/firmware.md b/user-interface/firmware.md index 20929dc..45546dc 100644 --- a/user-interface/firmware.md +++ b/user-interface/firmware.md @@ -10,13 +10,13 @@ Firmware management service integrates across all OpenWiFi Gateways deployed in Firmware dashboard provides a single view for overall health of deployed device firmware. Latest firmware charts, device firmware version distribution, distribution of device by type and current connected devices. -![Firmware Dashboard](<../.gitbook/assets/Screen Shot 2021-08-01 at 12.07.27 PM.png>) +![Firmware Dashboard](../.gitbook/assets/screen-shot-2021-08-01-at-12.07.27-pm.png) ## Device Table From the Devices table, any device with a newer firmware published by TIP OpenWiFi is indicated with a yellow icon. Selecting this icon presents the option to upgrade to latest or specify which firmware to use. -![Firmware Control in Device Table](<../.gitbook/assets/Screen Shot 2021-08-01 at 12.08.45 PM.png>) +![Firmware Control in Device Table](../.gitbook/assets/screen-shot-2021-08-01-at-12.08.45-pm.png) When the upgrade has been sent successfully, a green Success dialog will display in the upper right on the screen. Devices with latest firmware version will show a green firmware icon in the Devices row. @@ -26,10 +26,10 @@ Viewing the contents of Firmware Management Service is available from the left n Once in Firmware, it is possible to search by device model for all known firmware revisions. -![Firmware Management Service](<../.gitbook/assets/Screen Shot 2021-07-29 at 4.43.57 PM.png>) +![Firmware Management Service](../.gitbook/assets/screen-shot-2021-07-29-at-4.43.57-pm.png) If in the Device Table reference above, instead of selecting Upgrade to Latest, the specific URI location of any available firmware is found using the Firmware table. Selecting Details will present information for any firmware row, including the URI which may be copied into the Choose Custom Firmware dialog prompt accordingly. -![Firmware Entry Details](<../.gitbook/assets/Screen Shot 2021-07-29 at 4.46.01 PM.png>) +![Firmware Entry Details](../.gitbook/assets/screen-shot-2021-07-29-at-4.46.01-pm.png)