content/device.js (225 lines of code) (raw):
import {
AzDpsClient,
createHmac
} from './AzDpsClient.js'
import {
AzIoTHubClient,
ackPayload
} from './AzIoTHubClient.js'
const createApp = () => {
let telemetryInterval
let reportedInterval
let consoleEntries = 0
const maxConsoleEntries = 200
/** @type {AzIoTHubClient} client */
let client
// @ts-ignore
const app = new Vue({
el: '#app',
data: {
saveConfig: true,
viewDpsForm: false,
disableDeviceKey: false,
runningProvision: false,
/** @type {ConnectionInfo} */
connectionInfo: {
scopeId: '',
hubName: '',
deviceId: 'SimpleDevice01',
deviceKey: '',
modelId: 'dtmi:simpleModel:simplesample;1',
status: 'Disconnected',
connected: false
},
/** @type {Array<CommandInfo>} */
isTelemetryRunning: false,
statusConsole:''
},
async created() {
/** @type { ConnectionInfo } connInfo */
const connInfo = JSON.parse(window.localStorage.getItem('connectionInfo') || '{}')
connInfo.deviceId = connInfo.deviceId
if (connInfo.scopeId) {
this.connectionInfo.scopeId = connInfo.scopeId
if (connInfo.masterKey) {
this.connectionInfo.masterKey = connInfo.masterKey
this.connectionInfo.deviceKey = await createHmac(this.connectionInfo.masterKey, this.connectionInfo.deviceId)
}
}
if (connInfo.hubName) {
this.connectionInfo.hubName = connInfo.hubName
this.connectionInfo.deviceId = connInfo.deviceId
this.connectionInfo.deviceKey = connInfo.deviceKey
this.connectionInfo.modelId = connInfo.modelId
}
},
methods: {
writeToConsole(content, color) {
if (consoleEntries >= maxConsoleEntries) {
this.statusConsole = this.statusConsole.substring(this.statusConsole.indexOf('</div>')+6)
consoleEntries--
}
this.statusConsole += '<div style="color: ' + color + ';">' + content + '</div>'
consoleEntries++
},
async provision() {
window.localStorage.setItem('connectionInfo',
JSON.stringify({
scopeId: this.connectionInfo.scopeId,
hubName: this.connectionInfo.hubName,
deviceId: this.connectionInfo.deviceId,
deviceKey: this.connectionInfo.deviceKey,
masterKey: this.connectionInfo.masterKey,
modelId: this.connectionInfo.modelId
}))
const dpsClient = new AzDpsClient(this.connectionInfo.scopeId, this.connectionInfo.deviceId, this.connectionInfo.deviceKey, this.connectionInfo.modelId)
this.runningProvision = true
const result = await dpsClient.registerDevice()
this.runningProvision = false
if (result.status === 'assigned') {
this.connectionInfo.hubName = result.registrationState.assignedHub
this.connect()
} else {
console.log(result)
this.connectionInfo.hubName = result.status
}
this.viewDpsForm = false
},
async refreshDeviceId() {
this.com
this.connectionInfo.deviceId = 'device' + Date.now()
await this.updateDeviceKey()
},
async desiredPropertyAck(patch, status, statusMsg) {
// acknowledge the desired property back to IoT Central
const patchJSON = JSON.parse(patch)
const keyName = Object.keys(patchJSON)[0]
let reported_payload = {}
reported_payload[keyName] = {"value": patchJSON[keyName], "ac":status,"ad":statusMsg,"av":patchJSON['$version']}
await client.updateTwin(JSON.stringify(reported_payload))
this.writeToConsole("Desired property patch acknowledged: " + "<pre>" + this.syntaxHighlight(reported_payload) + "</pre>", "cyan")
},
async processDirectMethods(method, payload, rid) {
this.writeToConsole("Direct Method received: <pre>" + method + "(" + payload + ")</pre>", "green")
let response = 'unknown command'
let status = 404
if (method == 'sendTextMessage') {
response = {"messageRead": true}
status = 200
}
this.writeToConsole("Direct Method response: <pre>(status: " + status + ", payload: " + "<pre>" + this.syntaxHighlight(response) + "</pre>" + ")</pre>", "green")
await client.commandResponse(method, JSON.stringify(response), rid, status)
},
async processDesiredPropertyPatch(patch) {
this.writeToConsole("Desired property patch received: " + "<pre>" + this.syntaxHighlight(patch) + "</pre>", "cyan")
await this.desiredPropertyAck(patch, 200, "completed")
},
async processCloudToDeviceMessage(methodName, payload) {
this.writeToConsole("Cloud to Device message received: <pre>" + methodName + "(" + payload + ")</pre>", "red")
},
async connect() {
if (this.saveConfig) {
window.localStorage.setItem('connectionInfo',
JSON.stringify({
scopeId: this.connectionInfo.scopeId,
hubName: this.connectionInfo.hubName,
deviceId: this.connectionInfo.deviceId,
deviceKey: this.connectionInfo.deviceKey,
masterKey: this.connectionInfo.masterKey,
modelId: this.connectionInfo.modelId
}))
}
let host = this.connectionInfo.hubName
if (host.indexOf('.azure-devices.net') === -1) {
host += '.azure-devices.net'
}
client = new AzIoTHubClient(host,
this.connectionInfo.deviceId,
this.connectionInfo.deviceKey,
this.connectionInfo.modelId)
client.setDirectMethodCallback(this.processDirectMethods)
client.setDesiredPropertyCallback(this.processDesiredPropertyPatch)
client.setCloudToDeviceCallback(this.processCloudToDeviceMessage)
client.disconnectCallback = (err) => {
console.log(err)
this.connectionInfo.connected = false
this.connectionInfo.status = 'Disconnected'
}
await client.connect()
this.connectionInfo.status = 'Connected'
this.connectionInfo.connected = true
},
getRandomArbitrary(min, max, decimals) {
return +((Math.random() * (max - min) + min).toFixed(decimals));
},
startTelemetry() {
telemetryInterval = setInterval(() => {
const telemetryMessage = {"temp": this.getRandomArbitrary(32, 110, 2), "humidity": this.getRandomArbitrary(0, 100, 2)}
this.writeToConsole("Sending telemetry: " + "<pre>" + this.syntaxHighlight(telemetryMessage) + "</pre>", "#DEFFFF")
client.sendTelemetry(JSON.stringify(telemetryMessage))
}, this.getRandomArbitrary(4500, 5500, 0))
reportedInterval = setInterval(() => {
const reportedMessage = {"fanspeed": this.getRandomArbitrary(0, 1000, 0)}
this.writeToConsole("Sending reported property: " + "<pre>" + this.syntaxHighlight(reportedMessage) + "</pre>", "orange")
client.updateTwin(JSON.stringify(reportedMessage))
}, this.getRandomArbitrary(9500, 10500, 0))
this.isTelemetryRunning = true
},
stopTelemetry() {
clearInterval(telemetryInterval)
clearInterval(reportedInterval)
this.isTelemetryRunning = false
},
clearConsole() {
this.statusConsole = ''
consoleEntries = 0
},
clearForm() {
window.localStorage.removeItem('connectionInfo')
this.connectionInfo = {
scopeId: '',
hubName: '',
deviceId: 'SimpleDevice01',
deviceKey: '',
modelId: 'dtmi:simpleModel:simplesample;1',
status: 'Disconnected',
connected: false
}
},
syntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2)
}
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number'
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key'
} else {
cls = 'string'
}
} else if (/true|false/.test(match)) {
cls = 'boolean'
} else if (/null/.test(match)) {
cls = 'null'
}
return '<span class="' + cls + '">' + match + '</span>'
})
},
async fetchTwin() {
if (client.connected) {
const twin = await client.getTwin()
this.writeToConsole('<div style="color: white;">Current full twin:<pre>' + this.syntaxHighlight(twin) + '</pre></div>', 'white')
}
},
async updateDeviceKey() {
this.disableDeviceKey = true
this.connectionInfo.deviceKey = await createHmac(this.connectionInfo.masterKey, this.connectionInfo.deviceId)
}
},
computed: {
connectionString() {
return `HostName=${this.connectionInfo.hubName}.azure-devices.net;DeviceId=${this.connectionInfo.deviceId};SharedAccessKey=${this.connectionInfo.deviceKey}`
}
},
})
return app
}
(() => {
createApp()
})()