Skip to content
This repository has been archived by the owner on Feb 17, 2021. It is now read-only.

Commit

Permalink
style: enable eslint
Browse files Browse the repository at this point in the history
  • Loading branch information
coderbyheart committed Dec 5, 2019
1 parent 02307e7 commit 51bb7f7
Show file tree
Hide file tree
Showing 21 changed files with 411 additions and 241 deletions.
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "@bifravst/eslint-config-typescript"
}
3 changes: 2 additions & 1 deletion arm/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export const deploymentName = resourceGroupName
/**
* Returns the name of the Device Provisioning Service
*/
export const iotDeviceProvisioningServiceName = () => `${resourceGroupName()}ProvisioningService`
export const iotDeviceProvisioningServiceName = () =>
`${resourceGroupName()}ProvisioningService`
86 changes: 59 additions & 27 deletions cli/bifravst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,59 @@ import * as program from 'commander'
import chalk from 'chalk'
import * as path from 'path'
import { createCARootCommand } from './commands/create-ca-root'
import { IotHubClient } from "@azure/arm-iothub";
import { IotHubClient } from '@azure/arm-iothub'
import { IotDpsClient } from '@azure/arm-deviceprovisioningservices'
import { AzureCliCredentials } from "@azure/ms-rest-nodeauth";
import { createDeviceCertCommand } from './commands/create-device-cert';
import { connectCommand } from './commands/connect';
import { run } from './process/run';
import { proofCARootPossessionCommand } from './commands/proof-ca-possession';
import { createCAIntermediateCommand } from './commands/create-ca-intermediate';
import { iotDeviceProvisioningServiceName, resourceGroupName, deploymentName } from '../arm/resources';

const ioTHubDPSConnectionString = ({ deploymentName, resourceGroupName }: { deploymentName: string, resourceGroupName: string }) => async () => (await run({
command: 'az',
args: [
'group', 'deployment', 'show', '-g', resourceGroupName, '-n', deploymentName, '--query', 'properties.outputs.ioTHubDPSConnectionString.value'
]
})).replace(/"/g, '')
import { AzureCliCredentials } from '@azure/ms-rest-nodeauth'
import { createDeviceCertCommand } from './commands/create-device-cert'
import { connectCommand } from './commands/connect'
import { run } from './process/run'
import { proofCARootPossessionCommand } from './commands/proof-ca-possession'
import { createCAIntermediateCommand } from './commands/create-ca-intermediate'
import {
iotDeviceProvisioningServiceName,
resourceGroupName,
deploymentName,
} from '../arm/resources'

const ioTHubDPSConnectionString = ({
deploymentName,
resourceGroupName,
}: {
deploymentName: string
resourceGroupName: string
}) => async () =>
(
await run({
command: 'az',
args: [
'group',
'deployment',
'show',
'-g',
resourceGroupName,
'-n',
deploymentName,
'--query',
'properties.outputs.ioTHubDPSConnectionString.value',
],
})
).replace(/"/g, '')

const creds = async () => {
const creds = await AzureCliCredentials.create();
const creds = await AzureCliCredentials.create()

const { tokenInfo: { subscription } } = creds
const {
tokenInfo: { subscription },
} = creds

console.log(chalk.magenta('Subscription ID:'), chalk.yellow(subscription))

return creds
}

let currentCreds: Promise<AzureCliCredentials>;
let currentCreds: Promise<AzureCliCredentials>

const getCurrentCreds = () => {
const getCurrentCreds = async () => {
if (!currentCreds) currentCreds = creds()
return currentCreds
}
Expand All @@ -43,9 +66,18 @@ const bifravstCLI = async () => {
const deployment = deploymentName()
const dpsName = iotDeviceProvisioningServiceName()

const getIotHubConnectionString = ioTHubDPSConnectionString({ resourceGroupName: resourceGroup, deploymentName: deployment })
const getIotDpsClient = () => getCurrentCreds().then(creds => new IotDpsClient(creds, creds.tokenInfo.subscription))
const getIotClient = () => getCurrentCreds().then(creds => new IotHubClient(creds, creds.tokenInfo.subscription))
const getIotHubConnectionString = ioTHubDPSConnectionString({
resourceGroupName: resourceGroup,
deploymentName: deployment,
})
const getIotDpsClient = async () =>
getCurrentCreds().then(
creds => new IotDpsClient(creds, creds.tokenInfo.subscription),
)
const getIotClient = async () =>
getCurrentCreds().then(
creds => new IotHubClient(creds, creds.tokenInfo.subscription),
)

program.description('Bifravst Command Line Interface')

Expand All @@ -54,26 +86,26 @@ const bifravstCLI = async () => {
certsDir,
iotDpsClient: getIotDpsClient,
dpsName,
resourceGroup
resourceGroup,
}),
proofCARootPossessionCommand({
iotDpsClient: getIotDpsClient,
certsDir,
dpsName,
resourceGroup
resourceGroup,
}),
createCAIntermediateCommand({
certsDir,
ioTHubDPSConnectionString: getIotHubConnectionString,
iotDpsClient: getIotDpsClient
iotDpsClient: getIotDpsClient,
}),
createDeviceCertCommand({
iotClient: getIotClient,
certsDir
certsDir,
}),
connectCommand({
iotDpsClient: getIotDpsClient,
certsDir
certsDir,
}),
]

Expand Down
91 changes: 58 additions & 33 deletions cli/commands/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,39 @@ const deviceUiUrl = process.env.DEVICE_UI_LOCATION || ''

export const connectCommand = ({
certsDir,
iotDpsClient
iotDpsClient,
}: {
iotDpsClient: () => Promise<IotDpsClient>
certsDir: string
}): ComandDefinition => ({
command: 'connect <deviceId>',
action: async (deviceId: string) => {

const deviceFiles = deviceFileLocations({
certsDir,
deviceId
deviceId,
})

const [
deviceCert,
deviceKey,
] = await Promise.all([
const [deviceCert, deviceKey] = await Promise.all([
fs.readFile(deviceFiles.certWithChain, 'utf-8'),
fs.readFile(deviceFiles.privateKey, 'utf-8'),
])

let iotHub

try {
const registration = JSON.parse(await fs.readFile(deviceFiles.registration,
'utf-8')) as DeviceRegistrationState
const registration = JSON.parse(
await fs.readFile(deviceFiles.registration, 'utf-8'),
) as DeviceRegistrationState
iotHub = registration.assignedHub
} catch {

// Connect to Device Provisioning Service using MQTT
// @see https://docs.microsoft.com/en-us/azure/iot-dps/iot-dps-mqtt-support

const armDpsClient = await iotDpsClient()
const dps = await armDpsClient.iotDpsResource.get('bifravstProvisioningService', 'bifravst')
const dps = await armDpsClient.iotDpsResource.get(
'bifravstProvisioningService',
'bifravst',
)
const dpsHostname = dps.properties.serviceOperationsHostName as string
const idScope = dps.properties.idScope as string
console.log(chalk.magenta(`Connecting to`), chalk.yellow(dpsHostname))
Expand All @@ -74,32 +73,41 @@ export const connectCommand = ({
console.log(chalk.magenta('Connected:'), chalk.yellow(deviceId))

// The device should publish a register message to DPS using $dps/registrations/PUT/iotdps-register/?$rid={request_id} as a Topic Name. The payload should contain the Device Registration object in JSON format. In a successful scenario, the device will receive a response on the $dps/registrations/res/202/?$rid={request_id}&retry-after=x topic name where x is the retry-after value in seconds. The payload of the response will contain the RegistrationOperationStatus object in JSON format.
client.publish(dpsTopics.register(), JSON.stringify({
registrationId: deviceId
}))
client.publish(
dpsTopics.register(),
JSON.stringify({
registrationId: deviceId,
}),
)
})

// The device must poll the service periodically to receive the result of the device registration operation.
const p = new Promise<DeviceRegistrationState>((resolve, reject) => {
client.on('message', (topic, payload) => {
console.debug(chalk.magenta(topic), chalk.yellow(payload.toString()))
const message = JSON.parse(payload.toString())
if (topic.indexOf(dpsTopics.registrationResult(202)) === 0) {
if (topic.startsWith(dpsTopics.registrationResult(202))) {
const args = new URLSearchParams(`${parse(topic).query}`)
const { operationId, status } = message
console.log(chalk.magenta('Status:'), chalk.yellow(status))
console.log(chalk.magenta('Retry after:'), chalk.yellow(args.get('retry-after') as string))
console.log(
chalk.magenta('Retry after:'),
chalk.yellow(args.get('retry-after') as string),
)
setTimeout(() => {
// Assuming that the device has already subscribed to the $dps/registrations/res/# topic as indicated above, it can publish a get operationstatus message to the $dps/registrations/GET/iotdps-get-operationstatus/?$rid={request_id}&operationId={operationId} topic name. The operation ID in this message should be the value received in the RegistrationOperationStatus response message in the previous step.
// Assuming that the device has already subscribed to the $dps/registrations/res/# topic as indicated above, it can publish a get operationstatus message to the $dps/registrations/GET/iotdps-get-operationstatus/?$rid={request_id}&operationId={operationId} topic name. The operation ID in this message should be the value received in the RegistrationOperationStatus response message in the previous step.
client.publish(dpsTopics.registationStatus(operationId), '')
}, parseInt(args.get('retry-after') || '1', 10) * 1000)
return
}
// In the successful case, the service will respond on the $dps/registrations/res/200/?$rid={request_id} topic. The payload of the response will contain the RegistrationOperationStatus object. The device should keep polling the service if the response code is 202 after a delay equal to the retry-after period. The device registration operation is successful if the service returns a 200 status code.
if (topic.indexOf(dpsTopics.registrationResult(200)) === 0) {
if (topic.startsWith(dpsTopics.registrationResult(200))) {
const { status, registrationState } = message
console.log(chalk.magenta('Status:'), chalk.yellow(status))
console.log(chalk.magenta('IoT Hub:'), chalk.yellow(registrationState.assignedHub))
console.log(
chalk.magenta('IoT Hub:'),
chalk.yellow(registrationState.assignedHub),
)
resolve(registrationState)
}
reject(new Error(`Unexpected message on topic ${topic}!`))
Expand All @@ -117,11 +125,17 @@ export const connectCommand = ({

iotHub = registration.assignedHub

console.log(chalk.green(`Device registration succeeded with IotHub`), chalk.blueBright(iotHub))
console.log(
chalk.green(`Device registration succeeded with IotHub`),
chalk.blueBright(iotHub),
)

await fs.writeFile(deviceFiles.registration, JSON.stringify(registration, null, 2), 'utf-8')
await fs.writeFile(
deviceFiles.registration,
JSON.stringify(registration, null, 2),
'utf-8',
)
} finally {

console.log(chalk.magenta(`Connecting to`), chalk.yellow(`${iotHub}`))

const client = connect({
Expand All @@ -137,7 +151,7 @@ export const connectCommand = ({
})

let cfg = {
...defaultConfig
...defaultConfig,
}

let wsConnection: WebSocketConnection
Expand All @@ -159,7 +173,9 @@ export const connectCommand = ({
client.on('connect', async () => {
console.log(chalk.green('Connected:'), chalk.blueBright(deviceId))

const getTwinPropertiesTopic = deviceTopics.getTwinProperties(getTwinPropertiesRequestId)
const getTwinPropertiesTopic = deviceTopics.getTwinProperties(
getTwinPropertiesRequestId,
)
console.log(chalk.magenta('>'), chalk.yellow(getTwinPropertiesTopic))
client.publish(getTwinPropertiesTopic, '')

Expand All @@ -169,7 +185,10 @@ export const connectCommand = ({
onUpdate: update => {
console.log(chalk.magenta('<'), chalk.cyan(JSON.stringify(update)))
updateReportedRequestId = v4()
client.publish(deviceTopics.updateTwinReported(updateReportedRequestId), JSON.stringify(update))
client.publish(
deviceTopics.updateTwinReported(updateReportedRequestId),
JSON.stringify(update),
)
},
onWsConnection: c => {
console.log(chalk.magenta('[ws]'), chalk.cyan('connected'))
Expand All @@ -182,23 +201,30 @@ export const connectCommand = ({
client.on('message', (topic, payload) => {
console.log(chalk.magenta('<'), chalk.yellow(topic))
if (payload.length) {
console.log(
chalk.magenta('<'),
chalk.cyan(payload.toString()),
)
console.log(chalk.magenta('<'), chalk.cyan(payload.toString()))
}
if (topic === deviceTopics.twinResponse({ rid: getTwinPropertiesRequestId, status: 200 })) {
if (
topic ===
deviceTopics.twinResponse({
rid: getTwinPropertiesRequestId,
status: 200,
})
) {
const p = JSON.parse(payload.toString())
cfg = {
...cfg,
...p.desired.cfg
...p.desired.cfg,
}
console.log(chalk.blue('Config:'))
console.log(cfg)
sendConfigToUi()
return
}
if (deviceTopics.updateTwinReportedAccepted(updateReportedRequestId).test(topic)) {
if (
deviceTopics
.updateTwinReportedAccepted(updateReportedRequestId)
.test(topic)
) {
// pass
return
}
Expand All @@ -212,4 +238,3 @@ export const connectCommand = ({
},
help: 'Connect to the IoT Hub',
})

Loading

0 comments on commit 51bb7f7

Please sign in to comment.