Add command for updating Module Twin (#97)
* Add command for updating Module Twin * Better naming * Resolve comments
This commit is contained in:
Родитель
d49ec7f47c
Коммит
7ddf5eaf55
|
@ -21,10 +21,10 @@ Interact with Azure IoT Hub, IoT Device Management, IoT Edge Management, IoT Hub
|
|||
* Send C2D message to device
|
||||
* Monitor C2D message from IoT Hub
|
||||
* Invoke Direct Method
|
||||
* Get/update Device Twin
|
||||
* Edit Device Twin
|
||||
* Interact with Azure IoT Edge <sup>Preview</sup> (Install [Azure IoT Edge](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-edge) for more IoT Edge support)
|
||||
* List Edge Moudles
|
||||
* View Module Twin
|
||||
* Edit Module Twin
|
||||
* Manage Edge runtime
|
||||
* Create deployment for Edge device
|
||||
* Generate Edge setup configuration file
|
||||
|
|
18
package.json
18
package.json
|
@ -59,7 +59,9 @@
|
|||
"onCommand:azure-iot-toolkit.uninstallEdge",
|
||||
"onCommand:azure-iot-toolkit.loginToContainerRegistry",
|
||||
"onCommand:azure-iot-toolkit.generateEdgeSetupConfig",
|
||||
"onCommand:azure-iot-toolkit.createIoTHub"
|
||||
"onCommand:azure-iot-toolkit.createIoTHub",
|
||||
"onCommand:azure-iot-toolkit.getModuleTwin",
|
||||
"onCommand:azure-iot-toolkit.updateModuleTwin"
|
||||
],
|
||||
"main": "./out/src/extension",
|
||||
"contributes": {
|
||||
|
@ -129,7 +131,7 @@
|
|||
},
|
||||
{
|
||||
"command": "azure-iot-toolkit.getDeviceTwin",
|
||||
"title": "Get Device Twin",
|
||||
"title": "Edit Device Twin",
|
||||
"category": "Azure IoT Hub"
|
||||
},
|
||||
{
|
||||
|
@ -223,7 +225,12 @@
|
|||
},
|
||||
{
|
||||
"command": "azure-iot-toolkit.getModuleTwin",
|
||||
"title": "Get Module Twin",
|
||||
"title": "Edit Module Twin",
|
||||
"category": "Azure IoT Edge"
|
||||
},
|
||||
{
|
||||
"command": "azure-iot-toolkit.updateModuleTwin",
|
||||
"title": "Update Module Twin",
|
||||
"category": "Azure IoT Edge"
|
||||
}
|
||||
],
|
||||
|
@ -401,6 +408,11 @@
|
|||
"when": "resourceFilename == azure-iot-device-twin.json",
|
||||
"command": "azure-iot-toolkit.updateDeviceTwin",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"when": "resourceFilename == azure-iot-module-twin.json",
|
||||
"command": "azure-iot-toolkit.updateModuleTwin",
|
||||
"group": "navigation"
|
||||
}
|
||||
],
|
||||
"explorer/context": [
|
||||
|
|
|
@ -145,6 +145,10 @@ export class AzureIoTExplorer {
|
|||
}
|
||||
|
||||
public async getModuleTwin(moduleItem: ModuleItem) {
|
||||
this._iotEdgeExplorer.getModuleTwin(moduleItem);
|
||||
await this._iotEdgeExplorer.getModuleTwin(moduleItem);
|
||||
}
|
||||
|
||||
public async updateModuleTwin() {
|
||||
await this._iotEdgeExplorer.updateModuleTwin();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
"user strict";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as vscode from "vscode";
|
||||
|
||||
export class Constants {
|
||||
public static ExtensionId = "vsciot-vscode.azure-iot-toolkit";
|
||||
|
@ -21,6 +24,7 @@ export class Constants {
|
|||
|
||||
public static IoTHubDirectMethodLabel = "DirectMethod";
|
||||
public static IoTHubDeviceTwinLabel = "DeviceTwin";
|
||||
public static IoTHubModuleTwinLabel = "ModuleTwin";
|
||||
|
||||
public static IoTHubAILoadDeviceTreeEvent = "AZ.LoadDeviceTree";
|
||||
public static IoTHubAIStartMonitorEvent = "AZ.D2C.startMonitoring";
|
||||
|
@ -35,12 +39,18 @@ export class Constants {
|
|||
public static IoTHubAIGetDeviceTwinStartEvent = "AZ.DeviceTwin.Get.Start";
|
||||
public static IoTHubAIGetDeviceTwinDoneEvent = "AZ.DeviceTwin.Get.Done";
|
||||
public static IoTHubAIUpdateDeviceTwinEvent = "AZ.DeviceTwin.Update";
|
||||
public static DeviceTwinJosnFileName = "azure-iot-device-twin.json";
|
||||
public static DeviceTwinJosnFilePath: string;
|
||||
public static IoTHubAIEdgeDeployStartEvent = "Edge.Deploy.Start";
|
||||
public static IoTHubAIEdgeDeployDoneEvent = "AZ.Edge.Deploy.Done";
|
||||
public static IoTHubAICreateStartEvent = "General.IoTHub.Create.Start";
|
||||
public static IoTHubAICreateDoneEvent = "AZ.IoTHub.Create.Done";
|
||||
public static IoTHubAIGetModuleTwinStartEvent = "AZ.Edge.ModuleTwin.Get.Start";
|
||||
public static IoTHubAIGetModuleTwinDoneEvent = "AZ.Edge.ModuleTwin.Get.Done";
|
||||
public static IoTHubAIUpdateModuleTwinStartEvent = "AZ.Edge.ModuleTwin.Update.Start";
|
||||
public static IoTHubAIUpdateModuleTwinDoneEvent = "AZ.Edge.ModuleTwin.Update.Done";
|
||||
public static ModuleTwinJosnFileName = "azure-iot-module-twin.json";
|
||||
public static ModuleTwinJosnFilePath: string;
|
||||
public static IoTHubAILoadModuleTreeStartEvent = "AZ.Edge.LoadModuleTree.Start";
|
||||
public static IoTHubAILoadModuleTreeDoneEvent = "AZ.Edge.LoadModuleTree.Done";
|
||||
|
||||
|
@ -59,4 +69,12 @@ export class Constants {
|
|||
public static ShowIoTHubInfoKey = "showIoTHubInfo";
|
||||
public static ShowConnectionStringInputBoxKey = "showConnectionStringInputBox";
|
||||
public static IoTHubApiVersion = "2017-11-08-preview";
|
||||
|
||||
public static initialize(context: vscode.ExtensionContext) {
|
||||
const directory = context.storagePath ? context.storagePath : os.tmpdir();
|
||||
Constants.ModuleTwinJosnFilePath = path.join(directory, Constants.ModuleTwinJosnFileName);
|
||||
Constants.DeviceTwinJosnFilePath = path.join(directory, Constants.DeviceTwinJosnFileName);
|
||||
}
|
||||
|
||||
private static a;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"use strict";
|
||||
import * as vscode from "vscode";
|
||||
import { AzureIoTExplorer } from "./azureIoTExplorer";
|
||||
import { Constants } from "./constants";
|
||||
import { DeviceTree } from "./deviceTree";
|
||||
import { Executor } from "./executor";
|
||||
import { TelemetryClient } from "./telemetryClient";
|
||||
|
@ -11,6 +12,7 @@ import { TelemetryClient } from "./telemetryClient";
|
|||
export function activate(context: vscode.ExtensionContext) {
|
||||
TelemetryClient.sendEvent("extensionActivated");
|
||||
|
||||
Constants.initialize(context);
|
||||
let azureIoTExplorer = new AzureIoTExplorer(context);
|
||||
let deviceTree = new DeviceTree(context);
|
||||
|
||||
|
@ -136,6 +138,10 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
await azureIoTExplorer.getModuleTwin(moduleItem);
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand("azure-iot-toolkit.updateModuleTwin", async () => {
|
||||
await azureIoTExplorer.updateModuleTwin();
|
||||
}));
|
||||
|
||||
vscode.workspace.onDidChangeTextDocument((event) => azureIoTExplorer.replaceConnectionString(event));
|
||||
|
||||
context.subscriptions.push(vscode.window.onDidCloseTerminal((closedTerminal: vscode.Terminal) => {
|
||||
|
|
|
@ -166,6 +166,37 @@ export class IoTEdgeExplorer extends BaseExplorer {
|
|||
}
|
||||
|
||||
public async getModuleTwin(moduleItem: ModuleItem) {
|
||||
if (moduleItem) {
|
||||
await this.getModuleTwinById(moduleItem.deviceId, moduleItem.moduleId);
|
||||
}
|
||||
}
|
||||
|
||||
public async updateModuleTwin() {
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIUpdateModuleTwinStartEvent);
|
||||
const iotHubConnectionString = await Utility.getConnectionString(Constants.IotHubConnectionStringKey, Constants.IotHubConnectionStringTitle);
|
||||
if (!iotHubConnectionString) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const moduleTwinContent = await Utility.readFromActiveFile(Constants.ModuleTwinJosnFileName);
|
||||
if (!moduleTwinContent) {
|
||||
return;
|
||||
}
|
||||
const moduleTwinJson = JSON.parse(moduleTwinContent);
|
||||
this._outputChannel.show();
|
||||
this.outputLine(Constants.IoTHubModuleTwinLabel, `Update Module Twin for [${moduleTwinJson.deviceId}][${moduleTwinJson.moduleId}]...`);
|
||||
await Utility.updateModuleTwin(iotHubConnectionString, moduleTwinJson.deviceId, moduleTwinJson.moduleId, moduleTwinContent);
|
||||
this.outputLine(Constants.IoTHubModuleTwinLabel, `Module Twin updated successfully`);
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIUpdateModuleTwinDoneEvent, { Result: "Success" });
|
||||
await this.getModuleTwinById(moduleTwinJson.deviceId, moduleTwinJson.moduleId);
|
||||
} catch (error) {
|
||||
this.outputLine(Constants.IoTHubModuleTwinLabel, `Failed to update Module Twin: ${error}`);
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIUpdateModuleTwinDoneEvent, { Result: "Fail", Message: error });
|
||||
}
|
||||
}
|
||||
|
||||
private async getModuleTwinById(deviceId: string, moduleId: string) {
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIGetModuleTwinStartEvent);
|
||||
const iotHubConnectionString = await Utility.getConnectionString(Constants.IotHubConnectionStringKey, Constants.IotHubConnectionStringTitle);
|
||||
if (!iotHubConnectionString) {
|
||||
|
@ -173,12 +204,16 @@ export class IoTEdgeExplorer extends BaseExplorer {
|
|||
}
|
||||
|
||||
try {
|
||||
const content = await Utility.getModuleTwin(iotHubConnectionString, moduleItem.deviceId, moduleItem.moduleId);
|
||||
const textDocument = await vscode.workspace.openTextDocument({ content: JSON.stringify(content, null, 4), language: "json" });
|
||||
vscode.window.showTextDocument(textDocument);
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIGetModuleTwinDoneEvent, { Result: "Success"});
|
||||
const twin = await Utility.getModuleTwin(iotHubConnectionString, deviceId, moduleId);
|
||||
Utility.writeJson(Constants.ModuleTwinJosnFilePath, twin);
|
||||
const document = await vscode.workspace.openTextDocument(Constants.ModuleTwinJosnFilePath);
|
||||
if (document.isDirty) {
|
||||
throw new Error(`Your ${Constants.ModuleTwinJosnFileName} has unsaved changes. Please close or save the file. Then try again.`);
|
||||
}
|
||||
vscode.window.showTextDocument(document);
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIGetModuleTwinDoneEvent, { Result: "Success" });
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`Failed to get Module Twin: ${error}`);
|
||||
this.outputLine(Constants.IoTHubModuleTwinLabel, `Failed to get Module Twin: ${error}`);
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIGetModuleTwinDoneEvent, { Result: "Fail", Message: error });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,6 @@ import { DeviceItem } from "./Model/DeviceItem";
|
|||
import { TelemetryClient } from "./telemetryClient";
|
||||
import { Utility } from "./utility";
|
||||
|
||||
const deviceTwinJosnFileName = "azure-iot-device-twin.json";
|
||||
const deviceTwinJosnFilePath = path.join(os.tmpdir(), deviceTwinJosnFileName);
|
||||
|
||||
export class IotHubDeviceTwinExplorer extends BaseExplorer {
|
||||
constructor(outputChannel: vscode.OutputChannel) {
|
||||
super(outputChannel);
|
||||
|
@ -44,10 +41,10 @@ export class IotHubDeviceTwinExplorer extends BaseExplorer {
|
|||
this.outputLine(Constants.IoTHubDeviceTwinLabel, `Failed to get Device Twin: ${err.message}`);
|
||||
} else {
|
||||
this.outputLine(Constants.IoTHubDeviceTwinLabel, `Device Twin retrieved successfully`);
|
||||
fs.writeFileSync(deviceTwinJosnFilePath, `${JSON.stringify(twin, null, 4)}`);
|
||||
vscode.workspace.openTextDocument(deviceTwinJosnFilePath).then((document: vscode.TextDocument) => {
|
||||
Utility.writeJson(Constants.DeviceTwinJosnFilePath, twin);
|
||||
vscode.workspace.openTextDocument(Constants.DeviceTwinJosnFilePath).then((document: vscode.TextDocument) => {
|
||||
if (document.isDirty) {
|
||||
vscode.window.showWarningMessage(`Your ${deviceTwinJosnFileName} has unsaved changes. \
|
||||
vscode.window.showWarningMessage(`Your ${Constants.DeviceTwinJosnFileName} has unsaved changes. \
|
||||
Please close or save the file. Then try again.`);
|
||||
}
|
||||
vscode.window.showTextDocument(document);
|
||||
|
@ -57,24 +54,19 @@ export class IotHubDeviceTwinExplorer extends BaseExplorer {
|
|||
}
|
||||
|
||||
public async updateDeviceTwin() {
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIUpdateDeviceTwinEvent);
|
||||
let iotHubConnectionString = await Utility.getConnectionString(Constants.IotHubConnectionStringKey, Constants.IotHubConnectionStringTitle);
|
||||
if (!iotHubConnectionString) {
|
||||
return;
|
||||
}
|
||||
|
||||
TelemetryClient.sendEvent(Constants.IoTHubAIUpdateDeviceTwinEvent);
|
||||
const activeTextEditor = vscode.window.activeTextEditor;
|
||||
if (!activeTextEditor || !activeTextEditor.document || !activeTextEditor.document.fileName.endsWith(deviceTwinJosnFileName)) {
|
||||
vscode.window.showWarningMessage(`Please open ${deviceTwinJosnFileName} and try again.`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._outputChannel.show();
|
||||
let document = activeTextEditor.document;
|
||||
await document.save();
|
||||
let deviceTwinContent = activeTextEditor.document.getText();
|
||||
let deviceTwinContent = await Utility.readFromActiveFile(Constants.DeviceTwinJosnFileName);
|
||||
if (!deviceTwinContent) {
|
||||
return;
|
||||
}
|
||||
let deviceTwinJson = JSON.parse(deviceTwinContent);
|
||||
this._outputChannel.show();
|
||||
this.outputLine(Constants.IoTHubDeviceTwinLabel, `Update Device Twin for [${deviceTwinJson.deviceId}]...`);
|
||||
let registry = iothub.Registry.fromConnectionString(iotHubConnectionString);
|
||||
registry.updateTwin(deviceTwinJson.deviceId, deviceTwinContent, deviceTwinJson.etag, (err) => {
|
||||
|
|
|
@ -198,6 +198,32 @@ export class Utility {
|
|||
return (await axios.request(config)).data;
|
||||
}
|
||||
|
||||
public static async updateModuleTwin(iotHubConnectionString: string, deviceId: string, moduleId: string, twin: any): Promise<string> {
|
||||
const url = `/twins/${encodeURIComponent(deviceId)}/modules/${moduleId}?api-version=${Constants.IoTHubApiVersion}`;
|
||||
const config = Utility.generateIoTHubAxiosRequestConfig(iotHubConnectionString, url, "put", twin);
|
||||
|
||||
return (await axios.request(config)).data;
|
||||
}
|
||||
|
||||
public static async readFromActiveFile(fileName: string): Promise<string> {
|
||||
const activeTextEditor = vscode.window.activeTextEditor;
|
||||
if (!activeTextEditor || !activeTextEditor.document || path.basename(activeTextEditor.document.fileName) !== fileName) {
|
||||
vscode.window.showWarningMessage(`Please open ${fileName} and try again.`);
|
||||
return "";
|
||||
}
|
||||
const document = activeTextEditor.document;
|
||||
await document.save();
|
||||
return document.getText();
|
||||
}
|
||||
|
||||
public static writeJson(filePath: string, data) {
|
||||
const directory = path.dirname(filePath);
|
||||
if (!fs.existsSync(directory)) {
|
||||
fs.mkdirSync(directory);
|
||||
}
|
||||
fs.writeFileSync(filePath, `${JSON.stringify(data, null, 4)}`);
|
||||
}
|
||||
|
||||
public static async getInputDevice(deviceItem: DeviceItem, eventName: string, onlyEdgeDevice: boolean = false, iotHubConnectionString?: string): Promise<DeviceItem> {
|
||||
if (!deviceItem) {
|
||||
if (eventName) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче