diff --git a/agps/cacheKey.spec.ts b/agnss/cacheKey.spec.ts similarity index 100% rename from agps/cacheKey.spec.ts rename to agnss/cacheKey.spec.ts diff --git a/agps/cacheKey.ts b/agnss/cacheKey.ts similarity index 81% rename from agps/cacheKey.ts rename to agnss/cacheKey.ts index e84d09859..6f09cc733 100644 --- a/agps/cacheKey.ts +++ b/agnss/cacheKey.ts @@ -1,11 +1,11 @@ import { Static } from '@sinclair/typebox' -import { agpsRequestSchema } from './types.js' +import { agnssRequestSchema } from './types.js' export const cacheKey = ({ request, binHours, }: { - request: Static + request: Static binHours: number }): string => { const binMs = binHours * 60 * 60 * 1000 diff --git a/agps/types.ts b/agnss/types.ts similarity index 81% rename from agps/types.ts rename to agnss/types.ts index 9db25d678..a3f9d13b5 100644 --- a/agps/types.ts +++ b/agnss/types.ts @@ -1,6 +1,6 @@ import { Type } from '@sinclair/typebox' -export enum AGPSType { +export enum AGNSSType { 'UTC parameters' = 1, 'Ephemerides' = 2, 'Almanac' = 3, @@ -13,11 +13,11 @@ export enum AGPSType { const PositiveInteger = Type.Integer({ minimum: 1, title: 'positive integer' }) -export const agpsRequestSchema = Type.Object({ +export const agnssRequestSchema = Type.Object({ mcc: Type.Integer({ minimum: 100, maximum: 999 }), mnc: Type.Integer({ minimum: 0, maximum: 99 }), cell: PositiveInteger, area: PositiveInteger, phycell: Type.Optional(PositiveInteger), - types: Type.Array(Type.Enum(AGPSType), { minItems: 1 }), + types: Type.Array(Type.Enum(AGNSSType), { minItems: 1 }), }) diff --git a/agpsDeviceRequestsHandler/agpsDeviceRequestsHandler.ts b/agnssDeviceRequestsHandler/agnssDeviceRequestsHandler.ts similarity index 76% rename from agpsDeviceRequestsHandler/agpsDeviceRequestsHandler.ts rename to agnssDeviceRequestsHandler/agnssDeviceRequestsHandler.ts index 22b840352..2f3650a44 100644 --- a/agpsDeviceRequestsHandler/agpsDeviceRequestsHandler.ts +++ b/agnssDeviceRequestsHandler/agnssDeviceRequestsHandler.ts @@ -5,18 +5,18 @@ import { StorageSharedKeyCredential, } from '@azure/storage-queue' import { Static } from '@sinclair/typebox' -import { agpsRequestSchema } from '../agps/types.js' +import { agnssRequestSchema } from '../agnss/types.js' import { fromEnv } from '../lib/fromEnv.js' import { log, logError } from '../lib/log.js' import { validateWithJSONSchema } from '../lib/validateWithJSONSchema.js' -const validateAgpsRequest = validateWithJSONSchema(agpsRequestSchema) +const validateAgnssRequest = validateWithJSONSchema(agnssRequestSchema) const config = () => fromEnv({ storageAccountName: 'STORAGE_ACCOUNT_NAME', storageAccessKey: 'STORAGE_ACCESS_KEY', - agpsRequestsQueueName: 'AGPS_REQUESTS_QUEUE_NAME', + agnssRequestsQueueName: 'AGNSS_REQUESTS_QUEUE_NAME', })({ ...process.env, }) @@ -29,7 +29,7 @@ const config = () => * * The requests are put in a queue for resolving. */ -const agpsDeviceRequestsHandler: AzureFunction = async ( +const agnssDeviceRequestsHandler: AzureFunction = async ( context: Context, requests: ( | { @@ -48,13 +48,13 @@ const agpsDeviceRequestsHandler: AzureFunction = async ( let queueClient: QueueClient try { - const { storageAccountName, storageAccessKey, agpsRequestsQueueName } = + const { storageAccountName, storageAccessKey, agnssRequestsQueueName } = config() queueClient = new QueueServiceClient( `https://${storageAccountName}.queue.core.windows.net`, new StorageSharedKeyCredential(storageAccountName, storageAccessKey), - ).getQueueClient(agpsRequestsQueueName) + ).getQueueClient(agnssRequestsQueueName) await queueClient.create() } catch (error) { logError(context)({ error: (error as Error).message }) @@ -62,7 +62,7 @@ const agpsDeviceRequestsHandler: AzureFunction = async ( } // Find A-GNSS requests - const agpsRequests = requests + const agnssRequests = requests .map((request, i) => ({ request, deviceId: @@ -74,22 +74,22 @@ const agpsDeviceRequestsHandler: AzureFunction = async ( string >, })) - .filter(({ properties }) => properties.agps === 'get') + .filter(({ properties }) => properties.agnss === 'get') - if (agpsRequests.length === 0) { + if (agnssRequests.length === 0) { log(context)(`No A-GNSS requests found.`) return } - log(context)({ agpsRequests }) + log(context)({ agnssRequests }) // Build list of valid requests const deviceRequests: { - request: Static + request: Static deviceId: string }[] = [] - agpsRequests.forEach(({ request, deviceId }) => { - const valid = validateAgpsRequest(request) + agnssRequests.forEach(({ request, deviceId }) => { + const valid = validateAgnssRequest(request) if ('error' in valid) { logError(context)(JSON.stringify(valid.error)) return @@ -120,4 +120,4 @@ const agpsDeviceRequestsHandler: AzureFunction = async ( ) } -export default agpsDeviceRequestsHandler +export default agnssDeviceRequestsHandler diff --git a/agpsDeviceRequestsHandler/function.json b/agnssDeviceRequestsHandler/function.json similarity index 80% rename from agpsDeviceRequestsHandler/function.json rename to agnssDeviceRequestsHandler/function.json index 32dd79709..82c4af116 100644 --- a/agpsDeviceRequestsHandler/function.json +++ b/agnssDeviceRequestsHandler/function.json @@ -7,7 +7,7 @@ "eventHubName": "%IOTHUB_EVENTS_EVENT_HUB_NAME%", "connection": "IOTHUB_EVENTS_CONNECTION_STRING", "cardinality": "many", - "consumerGroup": "%AGPS_REQUESTS_IOT_EVENTS_CONSUMER_GROUP_NAME%" + "consumerGroup": "%AGNSS_REQUESTS_IOT_EVENTS_CONSUMER_GROUP_NAME%" } ], "scriptFile": "./handler.mjs" diff --git a/agnssDeviceRequestsHandler/handler.mjs b/agnssDeviceRequestsHandler/handler.mjs new file mode 100644 index 000000000..f84d3fbbd --- /dev/null +++ b/agnssDeviceRequestsHandler/handler.mjs @@ -0,0 +1,2 @@ +import handler from "../dist/agnssDeviceRequestsHandler/agnssDeviceRequestsHandler.js"; +export default handler; diff --git a/agpsQueuedDeviceRequestsHandler/agpsQueuedDeviceRequestsHandler.ts b/agnssQueuedDeviceRequestsHandler/agnssQueuedDeviceRequestsHandler.ts similarity index 77% rename from agpsQueuedDeviceRequestsHandler/agpsQueuedDeviceRequestsHandler.ts rename to agnssQueuedDeviceRequestsHandler/agnssQueuedDeviceRequestsHandler.ts index e2cae6f81..cc058ad37 100644 --- a/agpsQueuedDeviceRequestsHandler/agpsQueuedDeviceRequestsHandler.ts +++ b/agnssQueuedDeviceRequestsHandler/agnssQueuedDeviceRequestsHandler.ts @@ -8,46 +8,46 @@ import { import { Static } from '@sinclair/typebox' import iothubCommon from 'azure-iot-common' import iothub from 'azure-iothub' -import { cacheKey } from '../agps/cacheKey.js' -import { agpsRequestSchema } from '../agps/types.js' +import { cacheKey } from '../agnss/cacheKey.js' +import { agnssRequestSchema } from '../agnss/types.js' import { fromEnv } from '../lib/fromEnv.js' import { log, logError } from '../lib/log.js' import { parseConnectionString } from '../lib/parseConnectionString.js' const config = () => fromEnv({ - binHoursString: 'AGPS_BIN_HOURS', + binHoursString: 'AGNSS_BIN_HOURS', iotHubConnectionString: 'IOTHUB_CONNECTION_STRING', cosmosDbConnectionString: 'COSMOSDB_CONNECTION_STRING', storageAccountName: 'STORAGE_ACCOUNT_NAME', storageAccessKey: 'STORAGE_ACCESS_KEY', - maxResolutionTimeInMinutes: 'AGPS_MAX_RESOLUTION_TIME_IN_MINUTES', + maxResolutionTimeInMinutes: 'AGNSS_MAX_RESOLUTION_TIME_IN_MINUTES', initialDelayString: 'INITIAL_DELAY', delayFactorString: 'DELAY_FACTOR', - agpsRequestsDatabaseName: 'AGPS_REQUESTS_DATABASE_NAME', - agpsRequestsContainerName: 'AGPS_REQUESTS_CONTAINER_NAME', - agpsRequestsQueueName: 'AGPS_REQUESTS_QUEUE_NAME', - agpsRequestsNrfCloudQueueName: 'AGPS_REQUESTS_NRFCLOUD_QUEUE_NAME', + agnssRequestsDatabaseName: 'AGNSS_REQUESTS_DATABASE_NAME', + agnssRequestsContainerName: 'AGNSS_REQUESTS_CONTAINER_NAME', + agnssRequestsQueueName: 'AGNSS_REQUESTS_QUEUE_NAME', + agnssRequestsNrfCloudQueueName: 'AGNSS_REQUESTS_NRFCLOUD_QUEUE_NAME', })({ - AGPS_BIN_HOURS: '1', - AGPS_MAX_RESOLUTION_TIME_IN_MINUTES: '3', + AGNSS_BIN_HOURS: '1', + AGNSS_MAX_RESOLUTION_TIME_IN_MINUTES: '3', INITIAL_DELAY: '5', DELAY_FACTOR: '1.5', ...process.env, }) // Keep a local cache in case many devices requests the same location -export type AGPSDataCache = Static & { +export type AGNSSDataCache = Static & { source: string dataHex?: string[] unresolved?: boolean updatedAt: Date } -const resolvedRequests: Record = {} +const resolvedRequests: Record = {} -type QueuedAGPSRequest = { +type QueuedAGNSSRequest = { deviceId: string - request: Static + request: Static timestamp: string delayInSeconds?: number } @@ -57,16 +57,16 @@ type QueuedAGPSRequest = { * a DB or kicking off the resoluting via a third-party API (currently only * nRF Cloud Assisted GPS Location Service is implemented.) */ -const agpsQueuedDeviceRequestsHandler: AzureFunction = async ( +const agnssQueuedDeviceRequestsHandler: AzureFunction = async ( context: Context, - { deviceId, request, delayInSeconds, timestamp }: QueuedAGPSRequest, + { deviceId, request, delayInSeconds, timestamp }: QueuedAGNSSRequest, ): Promise => { log(context)({ request, deviceId, delayInSeconds, timestamp, context }) let binHours: number let iotHubClient: iothub.Client let cosmosDbContainer: Container - let agpsRequestsQueueClient: QueueClient + let agnssRequestsQueueClient: QueueClient const resolverQueues: QueueClient[] = [] let maxResolutionTimeInSeconds: number let delayFactor: number @@ -82,10 +82,10 @@ const agpsQueuedDeviceRequestsHandler: AzureFunction = async ( delayFactorString, initialDelayString, cosmosDbConnectionString, - agpsRequestsDatabaseName, - agpsRequestsQueueName, - agpsRequestsContainerName, - agpsRequestsNrfCloudQueueName, + agnssRequestsDatabaseName, + agnssRequestsQueueName, + agnssRequestsContainerName, + agnssRequestsNrfCloudQueueName, } = config() binHours = parseInt(binHoursString, 10) @@ -100,21 +100,21 @@ const agpsQueuedDeviceRequestsHandler: AzureFunction = async ( }) cosmosDbContainer = cosmosClient - .database(agpsRequestsDatabaseName) - .container(agpsRequestsContainerName) + .database(agnssRequestsDatabaseName) + .container(agnssRequestsContainerName) - agpsRequestsQueueClient = new QueueServiceClient( + agnssRequestsQueueClient = new QueueServiceClient( `https://${storageAccountName}.queue.core.windows.net`, new StorageSharedKeyCredential(storageAccountName, storageAccessKey), - ).getQueueClient(agpsRequestsQueueName) - await agpsRequestsQueueClient.create() + ).getQueueClient(agnssRequestsQueueName) + await agnssRequestsQueueClient.create() - const nrfCloudAgpsRequestsQueueClient = new QueueServiceClient( + const nrfCloudAgnssRequestsQueueClient = new QueueServiceClient( `https://${storageAccountName}.queue.core.windows.net`, new StorageSharedKeyCredential(storageAccountName, storageAccessKey), - ).getQueueClient(agpsRequestsNrfCloudQueueName) - await nrfCloudAgpsRequestsQueueClient.create() - resolverQueues.push(nrfCloudAgpsRequestsQueueClient) + ).getQueueClient(agnssRequestsNrfCloudQueueName) + await nrfCloudAgnssRequestsQueueClient.create() + resolverQueues.push(nrfCloudAgnssRequestsQueueClient) maxResolutionTimeInSeconds = parseInt(maxResolutionTimeInMinutes, 10) * 60 delayFactor = parseFloat(delayFactorString) @@ -179,11 +179,11 @@ const agpsQueuedDeviceRequestsHandler: AzureFunction = async ( ) await Promise.all( (resolvedRequests[requestCacheKey]?.dataHex ?? []).map( - async (agpsdata) => { - const payload = Buffer.from(agpsdata, 'hex') + async (agnssdata) => { + const payload = Buffer.from(agnssdata, 'hex') log(context)(`Sending ${payload.length} bytes to ${deviceId}`) const m = new iothubCommon.Message(payload) - m.properties.add('agps', 'result') + m.properties.add('agnss', 'result') return iotHubClient.send(deviceId, m) }, ), @@ -222,7 +222,7 @@ const agpsQueuedDeviceRequestsHandler: AzureFunction = async ( const visibilityTimeout = Math.floor( Math.min(900, (delayInSeconds ?? initialDelay) * delayFactor), ) - await agpsRequestsQueueClient.sendMessage( + await agnssRequestsQueueClient.sendMessage( Buffer.from( JSON.stringify({ deviceId, @@ -240,4 +240,4 @@ const agpsQueuedDeviceRequestsHandler: AzureFunction = async ( log(context)(requestCacheKey, `re-scheduled request for`, deviceId) } -export default agpsQueuedDeviceRequestsHandler +export default agnssQueuedDeviceRequestsHandler diff --git a/agpsQueuedDeviceRequestsHandler/function.json b/agnssQueuedDeviceRequestsHandler/function.json similarity index 75% rename from agpsQueuedDeviceRequestsHandler/function.json rename to agnssQueuedDeviceRequestsHandler/function.json index d78c726a1..0cd2449ad 100644 --- a/agpsQueuedDeviceRequestsHandler/function.json +++ b/agnssQueuedDeviceRequestsHandler/function.json @@ -4,7 +4,7 @@ "type": "queueTrigger", "direction": "in", "name": "request", - "queueName": "%AGPS_REQUESTS_QUEUE_NAME%" + "queueName": "%AGNSS_REQUESTS_QUEUE_NAME%" } ], "scriptFile": "./handler.mjs" diff --git a/agnssQueuedDeviceRequestsHandler/handler.mjs b/agnssQueuedDeviceRequestsHandler/handler.mjs new file mode 100644 index 000000000..24c5d09c0 --- /dev/null +++ b/agnssQueuedDeviceRequestsHandler/handler.mjs @@ -0,0 +1,2 @@ +import handler from "../dist/agnssQueuedDeviceRequestsHandler/agnssQueuedDeviceRequestsHandler.js"; +export default handler; diff --git a/agpsResolveRequestFromNrfCloud/agps.ts b/agnssResolveRequestFromNrfCloud/agnss.ts similarity index 67% rename from agpsResolveRequestFromNrfCloud/agps.ts rename to agnssResolveRequestFromNrfCloud/agnss.ts index f3e2409da..c68dc62c8 100644 --- a/agpsResolveRequestFromNrfCloud/agps.ts +++ b/agnssResolveRequestFromNrfCloud/agnss.ts @@ -1,6 +1,6 @@ import { verify } from '@nordicsemiconductor/nrfcloud-location-services-tests' import { Static, Type } from '@sinclair/typebox' -import { agpsRequestSchema, AGPSType } from '../agps/types.js' +import { agnssRequestSchema, AGNSSType } from '../agnss/types.js' import { ErrorInfo, ErrorType } from '../lib/ErrorInfo.js' import { validateWithJSONSchema } from '../lib/validateWithJSONSchema.js' import { apiClient } from '../third-party/nrfcloud.com/apiclient.js' @@ -14,24 +14,24 @@ const apiRequestSchema = Type.Object( requestType: Type.RegEx(/^custom$/), mcc: Type.Integer({ minimum: 100, maximum: 999 }), mnc: Type.Integer({ minimum: 0, maximum: 99 }), - customTypes: Type.Array(Type.Enum(AGPSType), { minItems: 1 }), + customTypes: Type.Array(Type.Enum(AGNSSType), { minItems: 1 }), }, { additionalProperties: false }, ) -const validateInput = validateWithJSONSchema(agpsRequestSchema) +const validateInput = validateWithJSONSchema(agnssRequestSchema) -export const resolveAgpsRequest = +export const resolveAgnssRequest = ( client: ReturnType, debug?: (...args: any[]) => void, error?: (...args: any[]) => void, ) => async ( - agps: Static, + agnss: Static, ): Promise<{ error: ErrorInfo } | readonly string[]> => { - debug?.({ agpsRequest: agps }) - const valid = validateInput(agps) + debug?.({ agnssRequest: agnss }) + const valid = validateInput(agnss) if ('error' in valid) { error?.(JSON.stringify(valid.error)) return valid @@ -40,17 +40,17 @@ export const resolveAgpsRequest = const { mcc, mnc, cell, area, types } = valid // Split requests, so that request for Ephemerides is a separate one - const otherTypesInRequest = types.filter((t) => t !== AGPSType.Ephemerides) + const otherTypesInRequest = types.filter((t) => t !== AGNSSType.Ephemerides) const requestTypes = [] - if (types.includes(AGPSType.Ephemerides)) - requestTypes.push([AGPSType.Ephemerides]) + if (types.includes(AGNSSType.Ephemerides)) + requestTypes.push([AGNSSType.Ephemerides]) if (otherTypesInRequest.length > 0) requestTypes.push(otherTypesInRequest) const res = [] for (const types of requestTypes) { const request = { - resource: 'location/agps', + resource: 'location/agnss', payload: { eci: cell, tac: area, @@ -73,7 +73,7 @@ export const resolveAgpsRequest = return { error: maybeHeaders.error } } - const maybeAgpsData = await client.getBinary({ + const maybeAgnssData = await client.getBinary({ ...request, headers: { ...request.headers, @@ -82,23 +82,23 @@ export const resolveAgpsRequest = requestSchema: apiRequestSchema, }) - if ('error' in maybeAgpsData) { - return { error: maybeAgpsData.error } + if ('error' in maybeAgnssData) { + return { error: maybeAgnssData.error } } - const maybeValidAgpsData = verify(maybeAgpsData) + const maybeValidAgnssData = verify(maybeAgnssData) - if ('error' in maybeValidAgpsData) { + if ('error' in maybeValidAgnssData) { return { error: { type: ErrorType.BadGateway, - message: `Could not verify A-GNSS payload: ${maybeValidAgpsData.error.message}!`, + message: `Could not verify A-GNSS payload: ${maybeValidAgnssData.error.message}!`, }, } } - debug?.({ agpsData: maybeValidAgpsData }) - res.push(maybeAgpsData.toString('hex')) + debug?.({ agnssData: maybeValidAgnssData }) + res.push(maybeAgnssData.toString('hex')) } return res diff --git a/agpsResolveRequestFromNrfCloud/agpsResolveRequestFromNrfCloud.ts b/agnssResolveRequestFromNrfCloud/agnssResolveRequestFromNrfCloud.ts similarity index 74% rename from agpsResolveRequestFromNrfCloud/agpsResolveRequestFromNrfCloud.ts rename to agnssResolveRequestFromNrfCloud/agnssResolveRequestFromNrfCloud.ts index 4c52406ff..cd6c1d120 100644 --- a/agpsResolveRequestFromNrfCloud/agpsResolveRequestFromNrfCloud.ts +++ b/agnssResolveRequestFromNrfCloud/agnssResolveRequestFromNrfCloud.ts @@ -2,33 +2,33 @@ import { Container, CosmosClient } from '@azure/cosmos' import { AzureFunction, Context } from '@azure/functions' import { Static } from '@sinclair/typebox' import { URL } from 'url' -import { cacheKey } from '../agps/cacheKey.js' -import { agpsRequestSchema } from '../agps/types.js' +import { cacheKey } from '../agnss/cacheKey.js' +import { agnssRequestSchema } from '../agnss/types.js' import { fromEnv } from '../lib/fromEnv.js' import { log, logError } from '../lib/log.js' import { parseConnectionString } from '../lib/parseConnectionString.js' import { apiClient } from '../third-party/nrfcloud.com/apiclient.js' -import { resolveAgpsRequest } from './agps.js' +import { resolveAgnssRequest } from './agnss.js' import { nrfCloudServiceKeyPromise as fetchServiceKey } from '../third-party/nrfcloud.com/config.js' const config = () => fromEnv({ - binHoursString: 'AGPS_BIN_HOURS', + binHoursString: 'AGNSS_BIN_HOURS', iotHubConnectionString: 'IOTHUB_CONNECTION_STRING', cosmosDbConnectionString: 'COSMOSDB_CONNECTION_STRING', storageAccountName: 'STORAGE_ACCOUNT_NAME', storageAccessKey: 'STORAGE_ACCESS_KEY', - maxResolutionTimeInMinutes: 'AGPS_MAX_RESOLUTION_TIME_IN_MINUTES', + maxResolutionTimeInMinutes: 'AGNSS_MAX_RESOLUTION_TIME_IN_MINUTES', initialDelayString: 'INITIAL_DELAY', delayFactorString: 'DELAY_FACTOR', keyVaultName: 'KEYVAULT_NAME', endpoint: 'NRFCLOUD_API_ENDPOINT', teamId: 'NRFCLOUD_TEAM_ID', - agpsRequestsDatabaseName: 'AGPS_REQUESTS_DATABASE_NAME', - agpsRequestsContainerName: 'AGPS_REQUESTS_CONTAINER_NAME', + agnssRequestsDatabaseName: 'AGNSS_REQUESTS_DATABASE_NAME', + agnssRequestsContainerName: 'AGNSS_REQUESTS_CONTAINER_NAME', })({ - AGPS_BIN_HOURS: '1', - AGPS_MAX_RESOLUTION_TIME_IN_MINUTES: '3', + AGNSS_BIN_HOURS: '1', + AGNSS_MAX_RESOLUTION_TIME_IN_MINUTES: '3', INITIAL_DELAY: '5', DELAY_FACTOR: '1.5', ...process.env, @@ -39,13 +39,13 @@ let nrfCloudServiceKeyPromise: Promise /** * Resolve A-GNSS requests from nRF Cloud */ -const agpsResolveRequestFromNrfCloud: AzureFunction = async ( +const agnssResolveRequestFromNrfCloud: AzureFunction = async ( context: Context, - request: Static, + request: Static, ): Promise => { log(context)({ context, request }) - let resolver: ReturnType + let resolver: ReturnType let cosmosDbContainer: Container let binHours: number @@ -56,13 +56,13 @@ const agpsResolveRequestFromNrfCloud: AzureFunction = async ( keyVaultName, cosmosDbConnectionString, binHoursString, - agpsRequestsDatabaseName, - agpsRequestsContainerName, + agnssRequestsDatabaseName, + agnssRequestsContainerName, } = config() if (nrfCloudServiceKeyPromise === undefined) nrfCloudServiceKeyPromise = fetchServiceKey(keyVaultName)() - resolver = resolveAgpsRequest( + resolver = resolveAgnssRequest( apiClient({ endpoint: new URL(endpoint), serviceKey: await nrfCloudServiceKeyPromise, @@ -89,14 +89,14 @@ const agpsResolveRequestFromNrfCloud: AzureFunction = async ( log(context)({ cosmosDb: { - database: agpsRequestsDatabaseName, - container: agpsRequestsContainerName, + database: agnssRequestsDatabaseName, + container: agnssRequestsContainerName, }, }) cosmosDbContainer = cosmosClient - .database(agpsRequestsDatabaseName) - .container(agpsRequestsContainerName) + .database(agnssRequestsDatabaseName) + .container(agnssRequestsContainerName) binHours = parseInt(binHoursString, 10) } catch (error) { @@ -129,4 +129,4 @@ const agpsResolveRequestFromNrfCloud: AzureFunction = async ( await cosmosDbContainer.items.upsert(item) } -export default agpsResolveRequestFromNrfCloud +export default agnssResolveRequestFromNrfCloud diff --git a/agpsResolveRequestFromNrfCloud/function.json b/agnssResolveRequestFromNrfCloud/function.json similarity index 71% rename from agpsResolveRequestFromNrfCloud/function.json rename to agnssResolveRequestFromNrfCloud/function.json index f53c60004..5ee1f7931 100644 --- a/agpsResolveRequestFromNrfCloud/function.json +++ b/agnssResolveRequestFromNrfCloud/function.json @@ -4,7 +4,7 @@ "type": "queueTrigger", "direction": "in", "name": "request", - "queueName": "%AGPS_REQUESTS_NRFCLOUD_QUEUE_NAME%" + "queueName": "%AGNSS_REQUESTS_NRFCLOUD_QUEUE_NAME%" } ], "scriptFile": "./handler.mjs" diff --git a/agnssResolveRequestFromNrfCloud/handler.mjs b/agnssResolveRequestFromNrfCloud/handler.mjs new file mode 100644 index 000000000..26cae8d52 --- /dev/null +++ b/agnssResolveRequestFromNrfCloud/handler.mjs @@ -0,0 +1,2 @@ +import handler from "../dist/agnssResolveRequestFromNrfCloud/agnssResolveRequestFromNrfCloud.js"; +export default handler; diff --git a/agpsDeviceRequestsHandler/handler.mjs b/agpsDeviceRequestsHandler/handler.mjs deleted file mode 100644 index 24438f366..000000000 --- a/agpsDeviceRequestsHandler/handler.mjs +++ /dev/null @@ -1,2 +0,0 @@ -import handler from "../dist/agpsDeviceRequestsHandler/agpsDeviceRequestsHandler.js"; -export default handler; diff --git a/agpsQueuedDeviceRequestsHandler/handler.mjs b/agpsQueuedDeviceRequestsHandler/handler.mjs deleted file mode 100644 index 08cb3916f..000000000 --- a/agpsQueuedDeviceRequestsHandler/handler.mjs +++ /dev/null @@ -1,2 +0,0 @@ -import handler from "../dist/agpsQueuedDeviceRequestsHandler/agpsQueuedDeviceRequestsHandler.js"; -export default handler; diff --git a/agpsResolveRequestFromNrfCloud/handler.mjs b/agpsResolveRequestFromNrfCloud/handler.mjs deleted file mode 100644 index a57efdb0b..000000000 --- a/agpsResolveRequestFromNrfCloud/handler.mjs +++ /dev/null @@ -1,2 +0,0 @@ -import handler from "../dist/agpsResolveRequestFromNrfCloud/agpsResolveRequestFromNrfCloud.js"; -export default handler; diff --git a/azuredeploy.json b/azuredeploy.json index a9cb6be25..84261fef2 100644 --- a/azuredeploy.json +++ b/azuredeploy.json @@ -102,22 +102,22 @@ "description": "Endpoint to use for the nRF Cloud API" } }, - "agpsBinHours": { + "agnssBinHours": { "type": "string", "defaultValue": "1", "metadata": { "description": "Number of hours to bin A-GNSS requests" } }, - "agpsRequestDatabaseName": { + "agnssRequestDatabaseName": { "type": "string", "minLength": 3, "metadata": { "description": "Name for the database that stores A-GNSS requests" }, - "defaultValue": "agpsRequests" + "defaultValue": "agnssRequests" }, - "agpsRequestContainerName": { + "agnssRequestContainerName": { "type": "string", "minLength": 3, "metadata": { @@ -125,29 +125,29 @@ }, "defaultValue": "cache" }, - "agpsRequestQueueName": { + "agnssRequestQueueName": { "type": "string", "minLength": 3, "metadata": { "description": "Name for the queue that stores A-GNSS requests" }, - "defaultValue": "agpsrequests" + "defaultValue": "agnssrequests" }, - "agpsRequestNrfCloudQueueName": { + "agnssRequestNrfCloudQueueName": { "type": "string", "minLength": 3, "metadata": { "description": "Name for the queue that stores A-GNSS requests to be resolved using the nRF Cloud API" }, - "defaultValue": "nrfcloudagpsrequests" + "defaultValue": "nrfcloudagnssrequests" }, - "agpsRequestIotEventsConsumerGroupName": { + "agnssRequestIotEventsConsumerGroupName": { "type": "string", "minLength": 3, "metadata": { "description": "Consumer group name for A-GNSS device requests" }, - "defaultValue": "agpsRequests" + "defaultValue": "agnssRequests" }, "pgpsBinHours": { "type": "string", @@ -334,7 +334,7 @@ { "type": "Microsoft.Devices/iotHubs/eventhubEndpoints/ConsumerGroups", "apiVersion": "2020-03-01", - "name": "[concat(parameters('appName'), 'IotHub', '/events/', parameters('agpsRequestIotEventsConsumerGroupName'))]", + "name": "[concat(parameters('appName'), 'IotHub', '/events/', parameters('agnssRequestIotEventsConsumerGroupName'))]", "dependsOn": [ "[resourceId('Microsoft.Devices/IotHubs', concat(parameters('appName'), 'IotHub'))]" ] @@ -554,28 +554,28 @@ "value": "[parameters('keyVaultName')]" }, { - "name": "AGPS_BIN_HOURS", - "value": "[parameters('agpsBinHours')]" + "name": "AGNSS_BIN_HOURS", + "value": "[parameters('agnssBinHours')]" }, { - "name": "AGPS_REQUESTS_IOT_EVENTS_CONSUMER_GROUP_NAME", - "value": "[parameters('agpsRequestIotEventsConsumerGroupName')]" + "name": "AGNSS_REQUESTS_IOT_EVENTS_CONSUMER_GROUP_NAME", + "value": "[parameters('agnssRequestIotEventsConsumerGroupName')]" }, { - "name": "AGPS_REQUESTS_DATABASE_NAME", - "value": "[parameters('agpsRequestDatabaseName')]" + "name": "AGNSS_REQUESTS_DATABASE_NAME", + "value": "[parameters('agnssRequestDatabaseName')]" }, { - "name": "AGPS_REQUESTS_CONTAINER_NAME", - "value": "[parameters('agpsRequestContainerName')]" + "name": "AGNSS_REQUESTS_CONTAINER_NAME", + "value": "[parameters('agnssRequestContainerName')]" }, { - "name": "AGPS_REQUESTS_QUEUE_NAME", - "value": "[parameters('agpsRequestQueueName')]" + "name": "AGNSS_REQUESTS_QUEUE_NAME", + "value": "[parameters('agnssRequestQueueName')]" }, { - "name": "AGPS_REQUESTS_NRFCLOUD_QUEUE_NAME", - "value": "[parameters('agpsRequestNrfCloudQueueName')]" + "name": "AGNSS_REQUESTS_NRFCLOUD_QUEUE_NAME", + "value": "[parameters('agnssRequestNrfCloudQueueName')]" }, { "name": "PGPS_BIN_HOURS", @@ -830,20 +830,20 @@ } ] ], - "defaultTtl": "[mul(mul(int(parameters('agpsBinHours')), 60), 60)]" + "defaultTtl": "[mul(mul(int(parameters('agnssBinHours')), 60), 60)]" } } }, { "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", "apiVersion": "2020-03-01", - "name": "[concat(parameters('appName'), '/', parameters('agpsRequestDatabaseName'))]", + "name": "[concat(parameters('appName'), '/', parameters('agnssRequestDatabaseName'))]", "dependsOn": [ "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('appName'))]" ], "properties": { "resource": { - "id": "[parameters('agpsRequestDatabaseName')]" + "id": "[parameters('agnssRequestDatabaseName')]" }, "options": {} } @@ -851,14 +851,14 @@ { "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", "apiVersion": "2020-03-01", - "name": "[concat(parameters('appName'), '/',parameters('agpsRequestDatabaseName'),'/', parameters('agpsRequestContainerName'))]", + "name": "[concat(parameters('appName'), '/',parameters('agnssRequestDatabaseName'),'/', parameters('agnssRequestContainerName'))]", "dependsOn": [ - "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('appName'), parameters('agpsRequestDatabaseName'))]", + "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('appName'), parameters('agnssRequestDatabaseName'))]", "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('appName'))]" ], "properties": { "resource": { - "id": "[parameters('agpsRequestContainerName')]", + "id": "[parameters('agnssRequestContainerName')]", "indexingPolicy": { "indexingMode": "consistent", "automatic": true, @@ -892,7 +892,7 @@ { "type": "Microsoft.Storage/storageAccounts/queueServices/queues", "apiVersion": "2021-04-01", - "name": "[concat(parameters('storageAccountName'), '/default/', parameters('agpsRequestQueueName'))]", + "name": "[concat(parameters('storageAccountName'), '/default/', parameters('agnssRequestQueueName'))]", "dependsOn": [ "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]" ], @@ -901,7 +901,7 @@ { "type": "Microsoft.Storage/storageAccounts/queueServices/queues", "apiVersion": "2021-04-01", - "name": "[concat(parameters('storageAccountName'), '/default/', parameters('agpsRequestNrfCloudQueueName'))]", + "name": "[concat(parameters('storageAccountName'), '/default/', parameters('agnssRequestNrfCloudQueueName'))]", "dependsOn": [ "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]" ], diff --git a/feature-runner/steps/device/matchDeviceBoundTopic.spec.ts b/feature-runner/steps/device/matchDeviceBoundTopic.spec.ts index b29694734..99410ffdd 100644 --- a/feature-runner/steps/device/matchDeviceBoundTopic.spec.ts +++ b/feature-runner/steps/device/matchDeviceBoundTopic.spec.ts @@ -22,7 +22,7 @@ void describe('matchTopic', () => { void it('should not match topic with a property bag thats not contained', () => assert.equal( matchDeviceBoundTopic( - 'devices/49dd7d86-e547-4a4d-8f0f-f4b09591838c/messages/devicebound/agps=result', + 'devices/49dd7d86-e547-4a4d-8f0f-f4b09591838c/messages/devicebound/agnss=result', 'devices/49dd7d86-e547-4a4d-8f0f-f4b09591838c/messages/devicebound/%24.to=%2Fdevices%2F49dd7d86-e547-4a4d-8f0f-f4b09591838c%2Fmessages%2Fdevicebound&pgps=result&%24.ct=application%2Fjson&%24.ce=utf-8', ), false, diff --git a/features/A-GPS-fan-out.feature b/features/A-GNSS-fan-out.feature similarity index 57% rename from features/A-GPS-fan-out.feature rename to features/A-GNSS-fan-out.feature index 8119c271b..e68f4101c 100644 --- a/features/A-GPS-fan-out.feature +++ b/features/A-GNSS-fan-out.feature @@ -18,19 +18,19 @@ Feature: A-GNSS Data Fan Out (The cargo container scenario) Scenario: Register and connect device Given I am run after the "A-GNSS" feature - And I have a random UUID in "agpsDevice" - And I generate a certificate for the device "{agpsDevice}" - And I connect the device "{agpsDevice}" + And I have a random UUID in "agnssDevice" + And I generate a certificate for the device "{agnssDevice}" + And I connect the device "{agnssDevice}" Scenario: Request A-GNSS data - When the device "{agpsDevice}" publishes this message to the topic devices/{agpsDevice}/messages/events/agps=get&%24.ct=application%2Fjson&%24.ce=utf-8 + When the device "{agnssDevice}" publishes this message to the topic devices/{agnssDevice}/messages/events/agnss=get&%24.ct=application%2Fjson&%24.ce=utf-8 """ { - "mcc": {agpsMcc}, - "mnc": {agpsMnc}, - "cell": {agpsCellId}, - "area": {agpsArea}, + "mcc": {agnssMcc}, + "mnc": {agnssMnc}, + "cell": {agnssCellId}, + "area": {agnssArea}, "types": [ 1, 2, @@ -43,14 +43,14 @@ Feature: A-GNSS Data Fan Out (The cargo container scenario) ] } """ - Then the device "{agpsDevice}" receives 2 raw messages on the topic devices/{agpsDevice}/messages/devicebound/agps=result into "agpsData" - And "$length($filter(agpsData, function($v) { $contains($v, '01010100f9fffffffeffffff0f7b12890612031f00017') })) > 0" should be true - And "$length($filter(agpsData, function($v) { $contains($v, '01021e0001006400c675009cff859f13000b0000c6753') })) > 0" should be true + Then the device "{agnssDevice}" receives 2 raw messages on the topic devices/{agnssDevice}/messages/devicebound/agnss=result into "agnssData" + And "$length($filter(agnssData, function($v) { $contains($v, '01010100f9fffffffeffffff0f7b12890612031f00017') })) > 0" should be true + And "$length($filter(agnssData, function($v) { $contains($v, '01021e0001006400c675009cff859f13000b0000c6753') })) > 0" should be true Scenario: Delete device Given the endpoint is "{apiEndpoint}" And the Authorization header is "Bearer {accessToken}" And the Content-Type header is "application/json; charset=utf-8" - When I DELETE /device/{agpsDevice} + When I DELETE /device/{agnssDevice} Then the response status code should be 202 \ No newline at end of file diff --git a/features/A-GPS.feature b/features/A-GNSS.feature similarity index 83% rename from features/A-GPS.feature rename to features/A-GNSS.feature index 070eb8742..41c571487 100644 --- a/features/A-GPS.feature +++ b/features/A-GNSS.feature @@ -8,32 +8,32 @@ Feature: A-GNSS two requests, one for type 2 (ephemerides) and one for the rest. Given I am run after the "Connect a tracker" feature - And I store a random number between 100 and 999 into "agpsMcc" - And I store a random number between 0 and 99 into "agpsMnc" - And I store a random number between 1 and 100000000 into "agpsCellId" - And I store a random number between 100 and 199 into "agpsArea" - And I enqueue this mock HTTP API response with status code 200 for a HEAD request to api.nrfcloud.com/v1/location/agps?customTypes=1%2C3%2C4%2C6%2C7%2C8%2C9&eci={agpsCellId}&mcc={agpsMcc}&mnc={agpsMnc}&requestType=custom&tac={agpsArea} + And I store a random number between 100 and 999 into "agnssMcc" + And I store a random number between 0 and 99 into "agnssMnc" + And I store a random number between 1 and 100000000 into "agnssCellId" + And I store a random number between 100 and 199 into "agnssArea" + And I enqueue this mock HTTP API response with status code 200 for a HEAD request to api.nrfcloud.com/v1/location/agnss?customTypes=1%2C3%2C4%2C6%2C7%2C8%2C9&eci={agnssCellId}&mcc={agnssMcc}&mnc={agnssMnc}&requestType=custom&tac={agnssArea} """ Content-Type: application/octet-stream Content-Length: 1160 """ - And I enqueue this mock HTTP API response with status code 200 for a GET request to api.nrfcloud.com/v1/location/agps?customTypes=1%2C3%2C4%2C6%2C7%2C8%2C9&eci={agpsCellId}&mcc={agpsMcc}&mnc={agpsMnc}&requestType=custom&tac={agpsArea} + And I enqueue this mock HTTP API response with status code 200 for a GET request to api.nrfcloud.com/v1/location/agnss?customTypes=1%2C3%2C4%2C6%2C7%2C8%2C9&eci={agnssCellId}&mcc={agnssMcc}&mnc={agnssMnc}&requestType=custom&tac={agnssArea} """ Content-Type: application/octet-stream Content-Length: 1160 01010100f9fffffffeffffff0f7b12890612031f00017b0f00af5ab01b5ffd001a0da1002bcf36004b0a24009c5d89ff7202fdff027b0f009fa5bb0d4cfd00860da10071533300c3e4c2ffd3e294ff6ffdffff037b0f003f1f331256fd00ec0da1004e11610093b3260008ca5d00f4fefcff047b0f00ec0a0b0c4efd00340da10063178dff517285fffa98cfff2aff0000057b0f00ea31b10949fd00240ca100e1855f005b6c27004b9cf3ffcaff0000067b0f008611511b5efd00210ca10011793600d107d8ff367894ff3b000200077b0f00dd7ca1054ffd00880da10015afb6ff0fdda1ff9ad67000ed000200087b0f008834e80f3afd00b80ca1005bf60a00917102008893e7ffdeff0000097b0f00af106c0746fd005b0da1009ffe8aff94db49006642f6ff88fe00000a7b0f00ef371c1256fd00000da10093f3600062dd96ffd82d390040fffeff0b7b0f003104610b4afdff190da100c8c4380007ab4c00aad80a00240001000c7b0f009443a3134cfd00300da100f2f8e3ff311232001cb75200a9ffffff0d7b0f00322bf51055fd00050da100ca1991ffbb0327000a5eceffb40001000e7b0f005308d70840fd00c60ca100d4d0e2ffc1aa7c001b6352001800feff0f7b0f00936e9ff732fd00c60ca10095df86ff6e3a2900dd28c0ff7aff0100107b0f00d663ac134bfd00900da10011bce4ff8da61b0045e0080078fefeff117b0f00166e9a194afd00cd0ca100962f0e006268c0ff5e07e6ff02020200127b0f00e10e161150fd00db0ca1003a3d37008f677600c1b297ff5d01ffff137b0f00a14bad184afd00cf0ca100740510005f234e009d6a47002a000100147b0f00362deffd39fd00a20ca10020045b003d2079000b6fb9ff21020000157b0f00f9c4f00948fd00da0ca100d54e3300b43cd3ffa103eaff90000100167b0f00d237ccfb36fd009f0da10066e65c007cfedaff557cb8ffccfd0300177b0f00a70cd80e52fd00ea0ca10046fa5f00f8fc6b00a54779004a00ffff187b0f00265dd9fa41fd00480da1002170b3ff277e1e0085b398ffdb000300197b0f009450600b42fd004c0ca1002bf0e0ff43772700df144b00c90002001a7b0f003431e8fe34fd006e0ca100e929dfff79fd0b00bec82f00810001001b7b0f00754d851542fd00240da10016b10b0085ee190054aae2ff45fffeff1d7b0f003e10d81a4cfd00640ca10034b30e00432e5d00db7ce6ff60fefeff1e7b0f00ea2bfbfb41fd00d90ca1006755b7ffaba990ffd74c6b001bfeffff1f7b0f00b7526c0853fd004f0ca1005d64b7ff26610b00e7425d0073ffffff207b0f007829fd0949fd002e0da100e56a8bff4d969fffc6c701000800ffff0401000502fffe2603fffc061e00017a0001027a0001037a0001047a0001057a0001067a0001077a0001087a0001097a00010a7a00010c7a00010d7a00010e7a00010f7a0001107a0001117a0001127a0001137a0001147a0001157a0001167a0001177a0001187a0001197a00011a7a00011b7a00011d7a00011e7a00011f7a0001207a00010701005b3b59be00000000000000000000000009010000040008080100bf325a000b69070000004141007f44 """ - And I enqueue this mock HTTP API response with status code 200 for a HEAD request to api.nrfcloud.com/v1/location/agps?customTypes=2&eci={agpsCellId}&mcc={agpsMcc}&mnc={agpsMnc}&requestType=custom&tac={agpsArea} + And I enqueue this mock HTTP API response with status code 200 for a HEAD request to api.nrfcloud.com/v1/location/agnss?customTypes=2&eci={agnssCellId}&mcc={agnssMcc}&mnc={agnssMnc}&requestType=custom&tac={agnssArea} """ Content-Type: application/octet-stream Content-Length: 1864 """ - And I enqueue this mock HTTP API response with status code 200 for a GET request to api.nrfcloud.com/v1/location/agps?customTypes=2&eci={agpsCellId}&mcc={agpsMcc}&mnc={agpsMnc}&requestType=custom&tac={agpsArea} + And I enqueue this mock HTTP API response with status code 200 for a GET request to api.nrfcloud.com/v1/location/agnss?customTypes=2&eci={agnssCellId}&mcc={agnssMcc}&mnc={agnssMnc}&requestType=custom&tac={agnssArea} """ Content-Type: application/octet-stream Content-Length: 1864 @@ -47,13 +47,13 @@ Feature: A-GNSS because A-GNSS Ephemerides data is so large it cannot be combined with other types - When the tracker "{trackerId}" publishes this message to the topic devices/{trackerId}/messages/events/agps=get&%24.ct=application%2Fjson&%24.ce=utf-8 + When the tracker "{trackerId}" publishes this message to the topic devices/{trackerId}/messages/events/agnss=get&%24.ct=application%2Fjson&%24.ce=utf-8 """ { - "mcc": {agpsMcc}, - "mnc": {agpsMnc}, - "cell": {agpsCellId}, - "area": {agpsArea}, + "mcc": {agnssMcc}, + "mnc": {agnssMnc}, + "cell": {agnssCellId}, + "area": {agnssArea}, "types": [ 1, 2, @@ -66,6 +66,6 @@ Feature: A-GNSS ] } """ - Then the tracker "{trackerId}" receives 2 raw messages on the topic devices/{trackerId}/messages/devicebound/agps=result into "agpsData" - And "$length($filter(agpsData, function($v) { $contains($v, '01010100f9fffffffeffffff0f7b12890612031f00017') })) > 0" should be true - And "$length($filter(agpsData, function($v) { $contains($v, '01021e0001006400c675009cff859f13000b0000c6753') })) > 0" should be true \ No newline at end of file + Then the tracker "{trackerId}" receives 2 raw messages on the topic devices/{trackerId}/messages/devicebound/agnss=result into "agnssData" + And "$length($filter(agnssData, function($v) { $contains($v, '01010100f9fffffffeffffff0f7b12890612031f00017') })) > 0" should be true + And "$length($filter(agnssData, function($v) { $contains($v, '01021e0001006400c675009cff859f13000b0000c6753') })) > 0" should be true \ No newline at end of file diff --git a/mock-http-api/sortQueryString.spec.ts b/mock-http-api/sortQueryString.spec.ts index 9fd6caaa9..02cf9179b 100644 --- a/mock-http-api/sortQueryString.spec.ts +++ b/mock-http-api/sortQueryString.spec.ts @@ -5,8 +5,8 @@ void describe('sortQueryString', () => { void it('should sort the query part of a mock URL', () => assert.equal( sortQueryString( - 'api.nrfcloud.com/v1/location/agps?eci=73393515&tac=132&requestType=custom&mcc=397&mnc=73&customTypes=2', + 'api.nrfcloud.com/v1/location/agnss?eci=73393515&tac=132&requestType=custom&mcc=397&mnc=73&customTypes=2', ), - 'api.nrfcloud.com/v1/location/agps?customTypes=2&eci=73393515&mcc=397&mnc=73&requestType=custom&tac=132', + 'api.nrfcloud.com/v1/location/agnss?customTypes=2&eci=73393515&mcc=397&mnc=73&requestType=custom&tac=132', )) })