├── .editorconfig ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── dotnet └── nuget_sample │ ├── README.md │ └── src │ ├── .nuget │ └── nuget.config │ ├── DotnetModuleSample.sln │ └── DotnetModuleSample │ ├── DotNetPrinterModule.cs │ ├── DotNetSensorModule.cs │ ├── DotnetModuleSample.csproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── SampleModule.cs │ ├── module_dev_sample.json │ └── packages.config ├── dotnetcore ├── nuget_sample │ ├── README.md │ └── src │ │ ├── .nuget │ │ └── nuget.config │ │ ├── NetstandardModuleSample.sln │ │ └── NetstandardModuleSample │ │ ├── DotNetSensorModule.cs │ │ ├── NetstandardModuleSample.csproj │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── SampleModule.cs │ │ └── module_dev_sample.json └── simulated_ble │ ├── README.md │ └── src │ ├── BleConverterData.cs │ ├── BleConverterModule.cs │ ├── BleData.cs │ ├── DotNetPrinterModule.cs │ ├── IoTEdgeConverterModule.csproj │ ├── binplace.ps1 │ └── gw-config.json ├── images ├── Dotnet_properties.png ├── NetStandard_properties.png ├── VSCode_BuildTask.png ├── VSCode_BuildTaskRunner.png ├── VSCode_Config.png ├── VSCode_Debug.png ├── VSCode_EditCsproj.png ├── VSCode_NewFile.png ├── VSCode_Rename.png ├── VSCode_Restore.png ├── VSCode_Run.png ├── VSCode_SaveAs.png ├── VSCode_UpdateCsproj.png ├── dataflow.png └── flow_chart.png ├── java ├── simulated_ble │ ├── README.md │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── microsoft │ │ │ └── azure │ │ │ └── gateway │ │ │ ├── ConverterModule.java │ │ │ └── PrinterModule.java │ │ └── resources │ │ └── gateway │ │ └── gw-config.json └── timer │ ├── README.md │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── microsoft │ │ │ └── azure │ │ │ └── gateway │ │ │ └── TimerModule.java │ └── resources │ │ └── gateway │ │ └── gw-config.json │ └── test │ └── java │ └── com │ └── microsoft │ └── azure │ └── gateway │ └── TimerModuleUnitTest.java └── js ├── converter ├── README.md ├── app.js ├── gw.config.json ├── modules │ ├── converter.js │ └── printer.js └── package.json └── simple ├── README.md ├── app.js ├── gw.cloud.config.json ├── gw.local.config.json ├── modules ├── iothub_writer.js ├── package.json ├── printer.js └── sensor.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | insert_final_newline = true 7 | 8 | # Matches multiple files with brace expansion notation 9 | # Set default charset 10 | [*] 11 | charset = utf-8 12 | 13 | # 2 space indentation 14 | [*] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Tab indentation (no size specified) 19 | [*] 20 | indent_style = space 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.cs text 7 | *.java text 8 | *.targets text 9 | *.nuspec text 10 | 11 | # Declare files that will always have CRLF line endings on checkout. 12 | *.js text eol=lf 13 | *.json text eol=lf 14 | *.md text eol=lf 15 | *.npmrc text eol=lf 16 | .gitattributes text eol=lf 17 | .gitignore text eol=lf 18 | .editorconfig eol=lf 19 | 20 | 21 | # Denote all files that are truly binary and should not be modified. 22 | *.png binary 23 | *.jpg binary 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | # VS Code 255 | .vscode 256 | 257 | # Java 258 | .classpath 259 | .project 260 | java/**/target/ 261 | java/**/.settings/ 262 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Edge Module Samples 2 | This tutorial shows how to setup your IoT Edge module development environment (Windows/Ubuntu Linux), write a module, customize and initialize the IoT Edge instance. It includes samples for JavaScript, Java, and .NET modules. 3 | 4 | If you encounter an issue related to these samples please [submit a new issue](https://github.com/Azure-Samples/iot-edge-samples/issues/new). For issues related to the IoT Edge or the packages please go to the [IoT Edge repo](https://github.com/Azure/iot-edge) and submit an issue. 5 | 6 |
7 | 8 | ## How to run the JavaScript module sample (Windows 10/Ubuntu 14+/Debian/Raspbian) 9 | ### Prerequisites 10 | 1. Install latest [Git Client](https://git-scm.com/downloads). 11 | 2. Install latest [Node LTS](https://nodejs.org) (v6.11.2). 12 | 13 | ### Raspbian: 14 | 1. Install [Raspbian-jessie](http://downloads.raspberrypi.org/raspbian/images/raspbian-2017-07-05/). 15 | 16 | ### Quick Start 17 | 1. `git clone https://github.com/Azure-Samples/iot-edge-samples.git` 18 | 2. `cd iot-edge-samples/js/simple` 19 | 3. `npm install` to install pre-built core runtime of IoT Edge. 20 | 4. `npm run local` to start the IoT Edge with pre-defined modules (sensor and printer). 21 | 22 |
23 | 24 | ## How to run the Java module sample (Windows 10/Ubuntu 14+) 25 | ### Prerequisites 26 | 1. Install latest [Git Client](https://git-scm.com/downloads). 27 | 2. Install latest x64 version of [JRE](http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html). 28 | 3. Install latest [Maven](https://maven.apache.org/install.html). 29 | ### Quick Start 30 | 1. `git clone https://github.com/Azure-Samples/iot-edge-samples.git` 31 | 2. `cd iot-edge-samples/java/timer` 32 | 3. `mvn package` to build your module with all dependencies. 33 | 4. `mvn exec:exec` to start the IoT Edge with pre-defined module. 34 | 35 |
36 | 37 | ## How to run the .NET module sample (Windows 10) 38 | ### Prerequisites 39 | 1. Install latest [Git Client](https://git-scm.com/downloads). 40 | 2. Install `Visual Studio 2015` with Update 3. 41 | ### Quick Start 42 | 1. `git clone https://github.com/Azure-Samples/iot-edge-samples.git` 43 | 2. `cd iot-edge-samples\dotnet\nuget_sample\src` 44 | 3. Open the `DotnetModuleSample.sln` solution file. 45 | 4. In the `Visual Studio 2015` IDE `Solution Explorer` right click the `DotnetModuleSample` and select `properties` from the context menu. 46 | 5. Click `Debug` and update the `Executable` text box with the location and name of the executable to run by typing "**<path to your output directory>\gw.exe**" and update the `Application arguments:` to `module_dev_sample.json`. 47 | 6. Build the DotnetModuleSample project (`Ctrl` + `Shift` + `B`). 48 | 7. Click the `Start` button in the `Visual Studio 2015` IDE or press the `F5` key. 49 | 8. Press the `Enter` key to exit the `Azure IoT Edge` gateway process. 50 | 51 | ## How to run .NET Standard v1.3 module sample (Windows 10) 52 | ### Prerequisites 53 | 1. Install latest [Git Client](https://git-scm.com/downloads). 54 | 2. Install `Visual Studio 2017`. 55 | ### Quick Start 56 | 1. `git clone https://github.com/Azure-Samples/iot-edge-samples.git` 57 | 2. `cd iot-edge-samples\dotnetcore\nuget_sample\src` 58 | 3. Open the `NetstandardModuleSample.sln` solution file. 59 | 4. In the `Visual Studio 2017 IDE` Solution Explorer right click the `NetstandardModuleSample` and select `properties` from the context menu. 60 | 5. Click `Debug` and update the `Executable` option to `$(OutDir)gw.exe` and the `Application arguments:` to `module_dev_sample.json`. 61 | 6. Build the `NetstandardModuleSample` project (`Ctrl` + `Shift` + `B`). 62 | 7. Click the `Start` button in the `Visual Studio 2017 IDE` or press the `F5` key. 63 | 8. Press the `Enter` key to exit the `Azure IoT Edge` gateway process. -------------------------------------------------------------------------------- /dotnet/nuget_sample/README.md: -------------------------------------------------------------------------------- 1 | .NET NuGet Package for Windows Desktop 2 | =============================== 3 | 4 | Overview 5 | ======== 6 | 7 | This sample showcases how one might build modules for `Azure IoT Edge` in .NET. 8 | 9 | The sample contains: 10 | 11 | 1. A printer module (C#) that interprets telemetry from sensor and prints its content and properties into Console. 12 | 2. A sensor module (C#) that publishes random data to the IoT Edge. 13 | 3. The .NET `Microsoft.Azure.IoT.Gateway` interface assembly. 14 | 4. A sample native (C) IoT Edge executable (gw.exe) file. 15 | 5. The native (C) binding layer interfaces for .NET, Java, and NodeJs (C). Which includes `aziotsharedutil.dll`, `dotnet.dll`, `dotnetcore.dll`, `gateway.dll`, `gw.exe`, `identity_map.dll`, `iothub.dll`, `iothub_client.dll`, `iothub_service_client.dll`, `java_module_host.dll`, `logger.dll`, `nanomsg.dll`, `node.dll`, `nodejs_binding.dll`, `simulated_device.dll`, and `serializer.dll`. 16 | 6. The `Microsoft.Azure.IoT.Gateway.dll` (C#) which contains the Azure IoT Edge module interface definition. 17 | 7. A `module_dev_sample.json` file that is used to configure which module the IoT Edge will use. 18 | 19 | Prerequisites 20 | ============= 21 | 1. Microsoft Visual Studio 2015. 22 | 2. Make sure you have .NET Framework installed. Our current version of the binding was tested and loads modules written in .NET version v4.6.01586. 23 | 3. The [Microsoft .NET Framework 4.5](https://www.microsoft.com/en-us/download/details.aspx?id=30653). 24 | 25 | How does the data flow through the IoT Edge 26 | =========================================== 27 | You can find the diagram for Receiving a message and publishing a message on this flow chart: 28 | 29 | ![](../../images/flow_chart.png) 30 | 31 | Running the sample 32 | ================== 33 | 1. Build the DotnetModuleSample project (`Ctrl` + `Shift` + `B`). 34 | 2. Click on the `DotnetModuleSample` and press `Alt` + `Enter` to open the `DotnetModuleSample` properties tab. 35 | 3. Click on the `Debug` option on the left hand side of the tab. 36 | 4. Update the `Executable` text box with the location and name of the executable to run by typing "**<path to your output directory>\gw.exe**" as seen in the image below. 37 | 5. Update the `Application arguments` text box with the arguments to be supplied the the Executable during execution by typing "**module_dev_sample.json**" as seen in the image below. 38 | 39 | ![](../../images/Dotnet_properties.png) 40 | 41 | 6. Click the `Start` button in the `Visual Studio 2015` IDE or press the `F5` key. 42 | 43 | **NOTE:** If you are making your own `Azure IoT Edge` module project and are unable to get the `Microsoft.Azure.Devices.Gateway.Native.Windows.x64` NuGet package binaries to bin place to the output directory you will need to add the below `XML` to your `.csproj` file to invoke the targets file before the MSBuild process builds your project. 44 | 45 | **XML:** 46 | 47 | ```xml 48 | 49 | 50 | 51 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 52 | 53 | 54 | 55 | ``` 56 | 57 | References 58 | ========== 59 | [Azure IoT Edge](https://azure.microsoft.com/campaigns/iot-edge/) -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/.nuget/nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetModuleSample", "DotnetModuleSample\DotnetModuleSample.csproj", "{4D14FECF-96BA-4B6B-94C7-919227CC1A2B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4D14FECF-96BA-4B6B-94C7-919227CC1A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4D14FECF-96BA-4B6B-94C7-919227CC1A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4D14FECF-96BA-4B6B-94C7-919227CC1A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4D14FECF-96BA-4B6B-94C7-919227CC1A2B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/DotNetPrinterModule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Microsoft.Azure.IoT.Gateway; 9 | 10 | 11 | namespace PrinterModule 12 | { 13 | public class DotNetPrinterModule : IGatewayModule 14 | { 15 | private string configuration; 16 | public void Create(Broker broker, byte[] configuration) 17 | { 18 | this.configuration = System.Text.Encoding.UTF8.GetString(configuration); 19 | } 20 | 21 | public void Destroy() 22 | { 23 | } 24 | 25 | public void Receive(Message received_message) 26 | { 27 | if (received_message.Properties["source"] == "sensor") 28 | { 29 | Console.WriteLine("Printer Module received message from Sensor. Content: " + System.Text.Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length)); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/DotNetSensorModule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Microsoft.Azure.IoT.Gateway; 9 | using System.Threading; 10 | 11 | namespace SensorModule 12 | { 13 | public class DotNetSensorModule : IGatewayModule, IGatewayModuleStart 14 | { 15 | private Broker broker; 16 | private string configuration; 17 | 18 | public void Create(Broker broker, byte[] configuration) 19 | { 20 | 21 | this.broker = broker; 22 | this.configuration = System.Text.Encoding.UTF8.GetString(configuration); 23 | 24 | } 25 | 26 | public void Start() 27 | { 28 | Thread oThread = new Thread(new ThreadStart(this.threadBody)); 29 | // Start the thread 30 | oThread.Start(); 31 | } 32 | 33 | public void Destroy() 34 | { 35 | } 36 | 37 | public void Receive(Message received_message) 38 | { 39 | //Just Ignore the Message. Sensor doesn't need to print. 40 | } 41 | 42 | public void threadBody() 43 | { 44 | Random r = new Random(); 45 | int n = r.Next(); 46 | 47 | while (true) 48 | { 49 | Dictionary thisIsMyProperty = new Dictionary(); 50 | thisIsMyProperty.Add("source", "sensor"); 51 | 52 | Message messageToPublish = new Message("SensorData: " + n, thisIsMyProperty); 53 | 54 | this.broker.Publish(messageToPublish); 55 | 56 | //Publish a message every 5 seconds. 57 | Thread.Sleep(5000); 58 | n = r.Next(); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/DotnetModuleSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4D14FECF-96BA-4B6B-94C7-919227CC1A2B} 8 | Library 9 | Properties 10 | DotnetModuleSample 11 | DotnetModuleSample 12 | v4.5.2 13 | 512 14 | 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | AnyCPU 26 | Program 27 | $(SolutionDir)DotnetModuleSample\bin\Debug\gw.exe 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | Program 37 | $(SolutionDir)DotnetModuleSample\bin\Release\gw.exe 38 | 39 | 40 | 41 | ..\packages\Microsoft.Azure.IoT.Gateway.Module.1.0.6\lib\net40\Microsoft.Azure.IoT.Gateway.dll 42 | True 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | PreserveNewest 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 70 | 71 | 72 | 73 | 80 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DotnetModuleSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DotnetModuleSample")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4d14fecf-96ba-4b6b-94c7-919227cc1a2b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/SampleModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Microsoft.Azure.IoT.Gateway; 4 | 5 | namespace DotnetModuleSample 6 | { 7 | public class SampleModule : IGatewayModule 8 | { 9 | private string configuration; 10 | public void Create(Broker broker, byte[] configuration) 11 | { 12 | this.configuration = Encoding.UTF8.GetString(configuration); 13 | } 14 | 15 | public void Destroy() 16 | { 17 | } 18 | 19 | public void Receive(Message received_message) 20 | { 21 | if (received_message.Properties["source"] == "sensor") 22 | { 23 | Console.WriteLine("SampleModule Module received message from Sensor. Content: {0}", Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length)); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/module_dev_sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "modules": [ 3 | { 4 | "name": "dotnet_sensor_module", 5 | "loader": { 6 | "name": "dotnet", 7 | "entrypoint": { 8 | "assembly.name": "DotNetModuleSample", 9 | "entry.type": "SensorModule.DotNetSensorModule" 10 | } 11 | }, 12 | "args": "module configuration" 13 | }, 14 | { 15 | "name": "dotnet_printer_module", 16 | "loader": { 17 | "name": "dotnet", 18 | "entrypoint": { 19 | "assembly.name": "DotNetModuleSample", 20 | "entry.type": "PrinterModule.DotNetPrinterModule" 21 | } 22 | }, 23 | "args": "module configuration" 24 | } 25 | ], 26 | "links": [ 27 | { 28 | "source": "dotnet_sensor_module", 29 | "sink": "dotnet_printer_module" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /dotnet/nuget_sample/src/DotnetModuleSample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/README.md: -------------------------------------------------------------------------------- 1 | .NET Standard v1.3 NuGet Package for Windows 10 Desktop 2 | =============================== 3 | 4 | Overview 5 | ======== 6 | 7 | This sample showcases how one might build modules for `Azure IoT Edge` in .NET Standard. 8 | 9 | The sample contains: 10 | 11 | 1. A printer module (C#) that interprets telemetry from sensor and prints its content and properties into Console. 12 | 2. A sensor module (C#) that publishes random data to the IoT Edge. 13 | 3. The .NET Core `Microsoft.Azure.Devices.Gateway` interface assembly. 14 | 4. A sample native (C) IoT Edge executable (gw.exe) file. 15 | 5. The native (C) binding layer interfaces for .NET, Java, and NodeJs (C). Which includes `aziotsharedutil.dll`, `dotnet.dll`, `dotnetcore.dll`, `gateway.dll`, `gw.exe`, `identity_map.dll`, `iothub.dll`, `iothub_client.dll`, `iothub_service_client.dll`, `java_module_host.dll`, `logger.dll`, `nanomsg.dll`, `node.dll`, `nodejs_binding.dll`, `simulated_device.dll`, and `serializer.dll`. 16 | 6. The `Microsoft.Azure.Devices.Gateway.dll` (C#) which contains the Azure IoT Edge module interface definition. 17 | 7. A `module_dev_sample.json` file that is used to configure which module the IoT Edge will use. 18 | 19 | Prerequisites 20 | ============= 21 | 1. Microsoft [Visual Studio 2017](https://docs.microsoft.com/en-us/visualstudio/install/install-visual-studio). 22 | 2. Make sure you have [.NET Core SDK](https://www.microsoft.com/net/core#windowscmd) installed. 23 | 3. The [Microsoft .NET Framework 4.5](https://www.microsoft.com/en-us/download/details.aspx?id=30653). 24 | 25 | How does the data flow through the IoT Edge 26 | =========================================== 27 | You can find the diagram for Receiving a message and publishing a message on this flow chart: 28 | 29 | ![](../../images/flow_chart.png) 30 | 31 | Running the sample 32 | ================== 33 | 1. Build the `NetstandardModuleSample` project (`Ctrl` + `Shift` + `B`). 34 | 2. Click on the `NetstandardModuleSample` and press `Alt` + `Enter` to open the `NetstandardModuleSample` properties tab. 35 | 3. Click on the `Debug` option on the left hand side of the tab. 36 | 4. Update the `Executable` text box with the location and name of the executable to run by typing "**$(OutDir)gw.exe**" as seen in the image below. 37 | 5. Update the `Application arguments` text box with the arguments to be supplied the the Executable during execution by typing "**module_dev_sample.json**" as seen in the image below. 38 | 39 | ![](../../images/NetStandard_properties.png) 40 | 41 | 6. Click the `Start` button in the `Visual Studio 2017` IDE or press the `F5` key. 42 | 43 | References 44 | ========== 45 | [Azure IoT Edge](https://azure.microsoft.com/campaigns/iot-edge/) -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/.nuget/nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/NetstandardModuleSample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.7 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetstandardModuleSample", "NetstandardModuleSample\NetstandardModuleSample.csproj", "{B799FB16-D1B6-4D4A-97CA-0879798A2757}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B799FB16-D1B6-4D4A-97CA-0879798A2757}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {B799FB16-D1B6-4D4A-97CA-0879798A2757}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {B799FB16-D1B6-4D4A-97CA-0879798A2757}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {B799FB16-D1B6-4D4A-97CA-0879798A2757}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/NetstandardModuleSample/DotNetSensorModule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading; 7 | using Microsoft.Azure.Devices.Gateway; 8 | 9 | namespace SensorModule 10 | { 11 | public class DotNetSensorModule : IGatewayModule, IGatewayModuleStart 12 | { 13 | private Broker broker; 14 | private string configuration; 15 | 16 | private Thread oThread; 17 | 18 | private bool quitThread = false; 19 | 20 | public void Create(Broker broker, byte[] configuration) 21 | { 22 | 23 | this.broker = broker; 24 | this.configuration = Encoding.UTF8.GetString(configuration); 25 | 26 | } 27 | 28 | public void Start() 29 | { 30 | oThread = new Thread(new ThreadStart(this.threadBody)); 31 | // Start the thread 32 | oThread.Start(); 33 | } 34 | 35 | public void Destroy() 36 | { 37 | quitThread = true; 38 | oThread.Join(); 39 | } 40 | 41 | public void Receive(Message received_message) 42 | { 43 | //Just Ignore the Message. Sensor doesn't need to print. 44 | } 45 | 46 | public void threadBody() 47 | { 48 | Random r = new Random(); 49 | int n = r.Next(); 50 | 51 | while (!quitThread) 52 | { 53 | Dictionary thisIsMyProperty = new Dictionary(); 54 | thisIsMyProperty.Add("source", "sensor"); 55 | 56 | Message messageToPublish = new Message("SensorData: " + n, thisIsMyProperty); 57 | 58 | this.broker.Publish(messageToPublish); 59 | 60 | //Publish a message every 5 seconds. 61 | Thread.Sleep(5000); 62 | n = r.Next(); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/NetstandardModuleSample/NetstandardModuleSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.3 5 | Program 6 | $(OutDir)gw.exe 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | PreserveNewest 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/NetstandardModuleSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "NetstandardModuleSample": { 4 | "commandName": "Executable", 5 | "executablePath": "$(OutDir)gw.exe", 6 | "commandLineArgs": "module_dev_sample.json", 7 | "environmentVariables": { 8 | "Key": "Value" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/NetstandardModuleSample/SampleModule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | using System; 4 | using System.Text; 5 | using Microsoft.Azure.Devices.Gateway; 6 | 7 | namespace NetstandardModuleSample 8 | { 9 | public class SampleModule : IGatewayModule 10 | { 11 | private string configuration; 12 | public void Create(Broker broker, byte[] configuration) 13 | { 14 | this.configuration = Encoding.UTF8.GetString(configuration); 15 | } 16 | 17 | public void Destroy() 18 | { 19 | } 20 | 21 | public void Receive(Message received_message) 22 | { 23 | if (received_message.Properties["source"] == "sensor") 24 | { 25 | Console.WriteLine("SampleModule received message from Sensor. Content: {0}", Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length)); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /dotnetcore/nuget_sample/src/NetstandardModuleSample/module_dev_sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [ 3 | { 4 | "type": "dotnetcore", 5 | "name": "dotnetcore", 6 | "configuration": { 7 | "binding.path": "dotnetcore.dll", 8 | "binding.coreclrpath": "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\1.1.1\\coreclr.dll", 9 | "binding.trustedplatformassemblieslocation": "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\1.1.1\\" 10 | } 11 | } 12 | ], 13 | "modules": [ 14 | { 15 | "name": "logger", 16 | "loader": { 17 | "name": "native", 18 | "entrypoint": { 19 | "module.path": "logger.dll" 20 | } 21 | }, 22 | "args": { 23 | "filename": "log.txt" 24 | } 25 | }, 26 | { 27 | "name": "dotnet_sensor_module", 28 | "loader": { 29 | "name": "dotnetcore", 30 | "entrypoint": { 31 | "assembly.name": "NetstandardModuleSample", 32 | "entry.type": "SensorModule.DotNetSensorModule" 33 | } 34 | }, 35 | "args": "module configuration" 36 | }, 37 | { 38 | "name": "dotnet_sample_module", 39 | "loader": { 40 | "name": "dotnetcore", 41 | "entrypoint": { 42 | "assembly.name": "NetstandardModuleSample", 43 | "entry.type": "NetstandardModuleSample.SampleModule" 44 | } 45 | }, 46 | "args": "module configuration" 47 | } 48 | ], 49 | "links": [ 50 | { 51 | "source": "dotnet_sensor_module", 52 | "sink": "dotnet_sample_module" 53 | } 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/README.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Edge BLE Data Converter Module with C# 2 | 3 | ## Overview 4 | 5 | This tutorial showcases how to create a module for `Azure IoT Edge` using `Visual Studio Code` and `C#`. 6 | 7 | In this tutorial, we will walk through environment setup and how to write a [BLE](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy) data converter module using the latest `Azure IoT Edge NuGet` packages. 8 | 9 | **NOTE:** This tutorial is using the `.NET Core SDK`, which supports cross-platform compatability, the following tutorial was written using the `Windows 10` operating system. Some of the commands in this tutorial may be different depending on your `development environment`. 10 | 11 | ## Prerequisites 12 | 13 | In this section, you will setup your environment for `Azure IoT Edge` module development. It applies to both **64-bit Windows** and **64-bit Linux (Ubuntu/Debian 8)** operating systems. 14 | 15 | The following software is required: 16 | 17 | 1. [Git Client](https://https://git-scm.com/downloads) 18 | 2. [.NET Core SDK](https://www.microsoft.com/net/core#windowscmd) 19 | 3. [Visual Studio Code](https://code.visualstudio.com/) 20 | 21 | **NOTE:** You do not need to clone the repo for this sample, however all of the sample code discussed in this tutorial is located in the `Azure-Samples` repository below. 22 | 23 | - `git clone https://github.com/Azure-Samples/iot-edge-samples.git`. 24 | - `cd iot-edge-samples/dotnetcore/simulated_ble` 25 | 26 | ## Getting Started 27 | 28 | 1. Install `.NET Core SDK`. 29 | 2. Install `Visual Studio Code` and the `C# extension` from the Visual Studio Code Marketplace. 30 | 31 | Please view this [quick video tutorial](https://channel9.msdn.com/Blogs/dotnet/Get-started-VSCode-Csharp-NET-Core-Windows) about how to get started using `Visual Studio Code` and the `.NET Core SDK`. 32 | 33 | ## Creating the Azure IoT Edge Converter Module 34 | 35 | 1. Initialize a new `.NET Core` class library C# project: 36 | - Open a command prompt (`Windows + R` -> `cmd` -> `enter`). 37 | - Navigate to the folder where you'd like to create the `C#` project. 38 | - Type "**dotnet new classlib -o IoTEdgeConverterModule -f netstandard1.3**". 39 | - This creates an empty class called `Class1.cs` in your projects directory. 40 | 2. Navigate to the folder where we just created the class library project by typing "**cd IoTEdgeConverterModule**". 41 | 3. Open the project in `Visual Studio Code` by typing "**code .**". 42 | 4. Once the project is opened in `Visual Studio Code`, in the file view to the left, click on the "**IoTEdgeConverterModule.csproj**". This will open the `IoTEdgeConverterModule.csproj` file in the code editor window to the right of the file view as shown in the image below. 43 | 44 | ![](../../images/VSCode_EditCsproj.png) 45 | 46 | 5. Insert the `XML` blob shown in the code snippet below between the closing `PropertyGroup` tag and the closing `Project` tag; line six in the above image and save the file (`Ctrl + S`). 47 | 48 | **XML:** 49 | 50 | ```xml 51 | 52 | 53 | 54 | 55 | 56 | ``` 57 | 6. Once you save the `.csproj` file `Visual Studio Code` should prompt you with an `unresolved dependencies` dialog as seen in the image below. 58 | 59 | ![](../../images/VSCode_Restore.png) 60 | 61 | - Click `Restore` to restore all of the references in the projects `.csproj` file including the `PackageReferences` we have just added. 62 | - You'll see a new `project.assets.json` file in your projects `obj` folder. This file contains information about your project's dependencies to make subsequent restores quicker. 63 | 64 | **NOTE:** `.NET Core Tools` are now MSBuild-based. This means a `.csproj` project file will be created instead of a `project.json`. 65 | 66 | If `Visual Studio Code` does not prompt you that is ok, we can do it manually. Open the `Visual Studio Code` integrated terminal window by pressing the `Ctrl` + `backtick` keys or using the menus `View` -> `Integrated Terminal`. 67 | - In the `Integrated Terminal` window type "**dotnet restore**". 68 | 69 | 7. Rename the `Class1.cs` file to `BleConverterModule.cs` by clicking on the file and pressing the `F2` key then typing **BleConverterModule** as seen in the image below. 70 | 71 | ![](../../images/VSCode_Rename.png) 72 | 73 | 8. Replace the existing code in the `BleConverterModule.cs` file by copying and pasting the below code snippit into your `BleConverterModule.cs` file. 74 | 75 | **C#:** 76 | 77 | ```csharp 78 | using System; 79 | using System.Collections.Generic; 80 | using System.Globalization; 81 | using System.Linq; 82 | using System.Text; 83 | using System.Threading; 84 | using System.Threading.Tasks; 85 | using Microsoft.Azure.Devices.Gateway; 86 | using Newtonsoft.Json; 87 | 88 | namespace IoTEdgeConverterModule 89 | { 90 | public class BleConverterModule : IGatewayModule, IGatewayModuleStart 91 | { 92 | private Broker broker; 93 | private string configuration; 94 | private int messageCount; 95 | 96 | public void Create(Broker broker, byte[] configuration) 97 | { 98 | this.broker = broker; 99 | this.configuration = System.Text.Encoding.UTF8.GetString(configuration); 100 | } 101 | 102 | public void Start() 103 | { 104 | } 105 | 106 | public void Destroy() 107 | { 108 | } 109 | 110 | public void Receive(Message received_message) 111 | { 112 | string recMsg = Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length); 113 | BleData receivedData = JsonConvert.DeserializeObject(recMsg); 114 | 115 | float temperature = float.Parse(receivedData.Temperature, CultureInfo.InvariantCulture.NumberFormat); 116 | Dictionary receivedProperties = received_message.Properties; 117 | 118 | Dictionary properties = new Dictionary(); 119 | properties.Add("source", receivedProperties["source"]); 120 | properties.Add("macAddress", receivedProperties["macAddress"]); 121 | properties.Add("temperatureAlert", temperature > 30 ? "true" : "false"); 122 | 123 | String content = String.Format("{0} \"deviceId\": \"Intel NUC Gateway\", \"messageId\": {1}, \"temperature\": {2} {3}", "{", ++this.messageCount, temperature, "}"); 124 | Message messageToPublish = new Message(content, properties); 125 | 126 | this.broker.Publish(messageToPublish); 127 | } 128 | } 129 | } 130 | ``` 131 | 132 | 11. Save the file by pressing `Ctrl` + `S`. 133 | 134 | 12. Create a new file by pressing the `Ctrl` + `N` keys, this will create a new file called `Untitled-1` as seen in the image below. 135 | 136 | ![](../../images/VSCode_NewFile.png) 137 | 138 | 13. Copy the below code into the `Untitled-1` file code editor window. This is the class that we will use to deserialize the `JSON` object that we receive from the simulated `BLE` device. 139 | 140 | **C#:** 141 | 142 | ```csharp 143 | using System; 144 | using Newtonsoft.Json; 145 | 146 | namespace IoTEdgeConverterModule 147 | { 148 | public class BleData 149 | { 150 | [JsonProperty(PropertyName = "temperature")] 151 | public string Temperature { get; set; } 152 | } 153 | } 154 | ``` 155 | 156 | 14. Save the file as `BleData.cs` by pressing `Ctrl` + `Shift` + `S` keys. 157 | - On the save as dialog box, in the `Save as Type` dropdown menu, select `C# (*.cs;*.csx)` as seen in the below image. 158 | 159 | ![](../../images/VSCode_SaveAs.png) 160 | 161 | 15. Create a new file by pressing the `Ctrl` + `N` keys, this will create a new file called `Untitled-1`. 162 | 163 | 16. Copy and paste the below code snippit into the `Untitled-1` file. This class is a `Azure IoT Edge` module which we will use to output the data received from our `BleConverterModule`. 164 | 165 | **C#:** 166 | 167 | ```csharp 168 | using System; 169 | using System.Collections.Generic; 170 | using System.Linq; 171 | using System.Text; 172 | using System.Threading.Tasks; 173 | using Microsoft.Azure.Devices.Gateway; 174 | using Newtonsoft.Json; 175 | 176 | namespace PrinterModule 177 | { 178 | public class DotNetPrinterModule : IGatewayModule 179 | { 180 | private string configuration; 181 | public void Create(Broker broker, byte[] configuration) 182 | { 183 | this.configuration = System.Text.Encoding.UTF8.GetString(configuration); 184 | } 185 | 186 | public void Destroy() 187 | { 188 | } 189 | 190 | public void Receive(Message received_message) 191 | { 192 | string recMsg = System.Text.Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length); 193 | Dictionary receivedProperties = received_message.Properties; 194 | 195 | BleConverterData receivedData = JsonConvert.DeserializeObject(recMsg); 196 | 197 | Console.WriteLine(); 198 | Console.WriteLine("Module : [DotNetPrinterModule]"); 199 | Console.WriteLine("received_message : {0}", recMsg); 200 | 201 | if(received_message.Properties["source"] == "bleTelemetry") 202 | { 203 | Console.WriteLine("Source : {0}", receivedProperties["source"]); 204 | Console.WriteLine("MAC address : {0}", receivedProperties["macAddress"]); 205 | Console.WriteLine("Temperature Alert: {0}", receivedProperties["temperatureAlert"]); 206 | Console.WriteLine("Deserialized Obj : [BleConverterData]"); 207 | Console.WriteLine(" DeviceId : {0}", receivedData.DeviceId); 208 | Console.WriteLine(" MessageId : {0}", receivedData.MessageId); 209 | Console.WriteLine(" Temperature : {0}", receivedData.Temperature); 210 | } 211 | 212 | Console.WriteLine(); 213 | } 214 | } 215 | } 216 | ``` 217 | 218 | 17. Save the file as `DotNetPrinterModule.cs` by pressing `Ctrl` + `Shift` + `S`. 219 | - On the save as dialog box, in the `Save as Type` dropdown menu, select `C# (*.cs;*.csx)`. 220 | 221 | 18. Create a new file by pressing the `Ctrl` + `N` keys. 222 | 223 | 19. Copy and paste the below code snippit into the `Untitled-1` file. This is the class that we will use to deserialize the `JSON` object that we receive from the `BleConverterModule`. 224 | 225 | **C#:** 226 | 227 | ```csharp 228 | using System; 229 | using Newtonsoft.Json; 230 | 231 | namespace PrinterModule 232 | { 233 | public class BleConverterData 234 | { 235 | [JsonProperty(PropertyName = "deviceId")] 236 | public string DeviceId { get; set; } 237 | 238 | [JsonProperty(PropertyName = "messageId")] 239 | public string MessageId { get; set; } 240 | 241 | [JsonProperty(PropertyName = "temperature")] 242 | public string Temperature { get; set; } 243 | } 244 | } 245 | ``` 246 | 247 | 20. Save the file as `BleConverterData.cs` by pressing `Ctrl` + `Shift` + `S`. 248 | - On the save as dialog box, in the `Save as Type` dropdown menu, select `C# (*.cs;*.csx)`. 249 | 250 | 21. Create a new file by pressing the `Ctrl` + `N` keys. 251 | 252 | 22. Copy and paste the below code snippit into the `Untitled-1` file. 253 | 254 | **JSON** 255 | 256 | ```json 257 | { 258 | "loaders": [ 259 | { 260 | "type": "dotnetcore", 261 | "name": "dotnetcore", 262 | "configuration": { 263 | "binding.path": "dotnetcore.dll", 264 | "binding.coreclrpath": "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\1.1.1\\coreclr.dll", 265 | "binding.trustedplatformassemblieslocation": "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\1.1.1\\" 266 | } 267 | } 268 | ], 269 | "modules": [ 270 | { 271 | "name": "simulated_device", 272 | "loader": { 273 | "name": "native", 274 | "entrypoint": { 275 | "module.path": "simulated_device.dll" 276 | } 277 | }, 278 | "args": { 279 | "macAddress": "01:02:03:03:02:01", 280 | "messagePeriod": 500 281 | } 282 | }, 283 | { 284 | "name": "ble_converter_module", 285 | "loader": { 286 | "name": "dotnetcore", 287 | "entrypoint": { 288 | "assembly.name": "IoTEdgeConverterModule", 289 | "entry.type": "IoTEdgeConverterModule.BleConverterModule" 290 | } 291 | }, 292 | "args": "" 293 | }, 294 | { 295 | "name": "printer_module", 296 | "loader": { 297 | "name": "dotnetcore", 298 | "entrypoint": { 299 | "assembly.name": "IoTEdgeConverterModule", 300 | "entry.type": "PrinterModule.DotNetPrinterModule" 301 | } 302 | }, 303 | "args": "" 304 | } 305 | ], 306 | "links": [ 307 | { 308 | "source": "simulated_device", "sink": "ble_converter_module" 309 | }, 310 | { 311 | "source": "ble_converter_module", "sink": "printer_module" 312 | } 313 | ] 314 | } 315 | ``` 316 | 317 | 23. Save the file as `gw-config.json` by pressing `Ctrl` + `Shift` + `S`. 318 | - On the save as dialog box, in the `Save as Type` dropdown menu, select `JSON (*.json;*.bowerrc;*.jshintrc;*.jscsrc;*.eslintrc;*.babelrc;*webmanifest)`. 319 | 320 | 24. Update the `IoTEdgeConverterModule.csproj` with the below XML blob to enable copying of the configuration file to the output directory. 321 | 322 | **XML:** 323 | 324 | ```xml 325 | 326 | 327 | 328 | ``` 329 | 330 | - The updated `IoTEdgeConverterModule.csproj` should look like the image below. 331 | 332 | ![](../../images/VSCode_UpdateCsproj.png) 333 | 334 | 25. Create a new file by pressing the `Ctrl` + `N` keys. 335 | 336 | 26. Copy and paste the below code snippit into the `Untitled-1` file. 337 | 338 | **PowerShell:** 339 | 340 | ```powershell 341 | Copy-Item -Path $env:userprofile\.nuget\packages\microsoft.azure.devices.gateway.native.windows.x64\1.1.3\runtimes\win-x64\native\* -Destination .\bin\Debug\netstandard1.3 342 | Copy-Item -Path $env:userprofile\.nuget\packages\system.runtime.serialization.formatters\4.3.0\lib\netstandard1.4\* -Destination .\bin\Debug\netstandard1.3 343 | Copy-Item -Path $env:userprofile\.nuget\packages\system.runtime.serialization.primitives\4.3.0\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 344 | Copy-Item -Path $env:userprofile\.nuget\packages\newtonsoft.json\10.0.2\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 345 | Copy-Item -Path $env:userprofile\.nuget\packages\system.componentmodel.typeconverter\4.3.0\lib\netstandard1.5\* -Destination .\bin\Debug\netstandard1.3 346 | Copy-Item -Path $env:userprofile\.nuget\packages\system.collections.nongeneric\4.3.0\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 347 | Copy-Item -Path $env:userprofile\.nuget\packages\system.collections.specialized\4.3.0\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 348 | ``` 349 | 350 | 27. Save the file as `binplace.ps1` by pressing `Ctrl` + `Shift` + `S`. 351 | - On the save as dialog box, in the `Save as Type` dropdown menu, select `PowerShell (*.ps1;*.psm1;*.psd1;*.pssc;*.psrc)`. 352 | 353 | 28. Buld the project (`Ctrl` + `Shift` + `B`), since this is the first time you have built the project `Visual Studio Code` will prompt you with the `No build task defined.` dialog as seen below. 354 | 355 | ![](../../images/VSCode_BuildTask.png) 356 | 357 | - Click the `Configure Build Task` button. 358 | - This will bring up the `Select a Task Runner` dialog dropdown menu. Since this is a `.NET Core` project, select `.Net Core` as seen in the image below. This will create the `tasks.json` file in your `.vscode` directory and open the file in the `code editor` window. There is no need to modify this file, simply close the tab by pressing (`Ctrl` + `F4`) or using the close button on the `tasks.json` tab itself. 359 | 360 | ![](../../images/VSCode_BuildTaskRunner.png) 361 | 362 | 29. Open the `Visual Studio Code` integrated terminal window by pressing the `Ctrl` + `backtick` keys or using the menus `View` -> `Integrated Terminal` and type "**.\binplace.ps1**" into the `PowerShell` command prompt. This will copy all our dependencies to the output directory. 363 | 364 | 30. Navigate to the projects output directory in the `Integrated Terminal` window by typing "**cd .\bin\Debug\netstandard1.3**". 365 | 366 | 367 | 31. Run the sample project by typing "**.\gw.exe gw-config.json**" into the `Integrated Terminal` window prompt. 368 | - If you have followed the steps in this tutorial closely you should now be running the `Azure IoT Edge BLE Data Converter Module` sample project as seen in the image below. 369 | - If you want to terminate the application, press the `` key. 370 | - ⚠ It is not recommended to use `Ctrl` + `C` to terminate the `IoT Edge` gateway application (i.e. **gw.exe**). As this may cause the process to terminate abnormally. 371 | 372 | ![](../../images/VSCode_Run.png) 373 | 374 | 375 | -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/BleConverterData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace PrinterModule 5 | { 6 | public class BleConverterData 7 | { 8 | [JsonProperty(PropertyName = "deviceId")] 9 | public string DeviceId { get; set; } 10 | 11 | [JsonProperty(PropertyName = "messageId")] 12 | public string MessageId { get; set; } 13 | 14 | [JsonProperty(PropertyName = "temperature")] 15 | public string Temperature { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/BleConverterModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Microsoft.Azure.Devices.Gateway; 9 | using Newtonsoft.Json; 10 | 11 | namespace IoTEdgeConverterModule 12 | { 13 | public class BleConverterModule : IGatewayModule, IGatewayModuleStart 14 | { 15 | private Broker broker; 16 | private string configuration; 17 | private int messageCount; 18 | 19 | public void Create(Broker broker, byte[] configuration) 20 | { 21 | this.broker = broker; 22 | this.configuration = System.Text.Encoding.UTF8.GetString(configuration); 23 | } 24 | 25 | public void Start() 26 | { 27 | } 28 | 29 | public void Destroy() 30 | { 31 | } 32 | 33 | public void Receive(Message received_message) 34 | { 35 | string recMsg = Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length); 36 | BleData receivedData = JsonConvert.DeserializeObject(recMsg); 37 | 38 | float temperature = float.Parse(receivedData.Temperature, CultureInfo.InvariantCulture.NumberFormat); 39 | Dictionary receivedProperties = received_message.Properties; 40 | 41 | Dictionary properties = new Dictionary(); 42 | properties.Add("source", receivedProperties["source"]); 43 | properties.Add("macAddress", receivedProperties["macAddress"]); 44 | properties.Add("temperatureAlert", temperature > 30 ? "true" : "false"); 45 | 46 | String content = String.Format("{0} \"deviceId\": \"Intel NUC Gateway\", \"messageId\": {1}, \"temperature\": {2} {3}", "{", ++this.messageCount, temperature, "}"); 47 | Message messageToPublish = new Message(content, properties); 48 | 49 | this.broker.Publish(messageToPublish); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/BleData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace IoTEdgeConverterModule 5 | { 6 | public class BleData 7 | { 8 | [JsonProperty(PropertyName = "temperature")] 9 | public string Temperature { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/DotNetPrinterModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.Azure.Devices.Gateway; 7 | using Newtonsoft.Json; 8 | 9 | namespace PrinterModule 10 | { 11 | public class DotNetPrinterModule : IGatewayModule 12 | { 13 | private string configuration; 14 | public void Create(Broker broker, byte[] configuration) 15 | { 16 | this.configuration = System.Text.Encoding.UTF8.GetString(configuration); 17 | } 18 | 19 | public void Destroy() 20 | { 21 | } 22 | 23 | public void Receive(Message received_message) 24 | { 25 | string recMsg = System.Text.Encoding.UTF8.GetString(received_message.Content, 0, received_message.Content.Length); 26 | Dictionary receivedProperties = received_message.Properties; 27 | 28 | BleConverterData receivedData = JsonConvert.DeserializeObject(recMsg); 29 | 30 | Console.WriteLine(); 31 | Console.WriteLine("Module : [DotNetPrinterModule]"); 32 | Console.WriteLine("received_message : {0}", recMsg); 33 | 34 | if(received_message.Properties["source"] == "bleTelemetry") 35 | { 36 | Console.WriteLine("Source : {0}", receivedProperties["source"]); 37 | Console.WriteLine("MAC address : {0}", receivedProperties["macAddress"]); 38 | Console.WriteLine("Temperature Alert: {0}", receivedProperties["temperatureAlert"]); 39 | Console.WriteLine("Deserialized Obj : [BleConverterData]"); 40 | Console.WriteLine(" DeviceId : {0}", receivedData.DeviceId); 41 | Console.WriteLine(" MessageId : {0}", receivedData.MessageId); 42 | Console.WriteLine(" Temperature : {0}", receivedData.Temperature); 43 | } 44 | 45 | Console.WriteLine(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/IoTEdgeConverterModule.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard1.3 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/binplace.ps1: -------------------------------------------------------------------------------- 1 | Copy-Item -Path $env:userprofile\.nuget\packages\microsoft.azure.devices.gateway.native.windows.x64\1.1.3\runtimes\win-x64\native\* -Destination .\bin\Debug\netstandard1.3 2 | Copy-Item -Path $env:userprofile\.nuget\packages\system.runtime.serialization.formatters\4.3.0\lib\netstandard1.4\* -Destination .\bin\Debug\netstandard1.3 3 | Copy-Item -Path $env:userprofile\.nuget\packages\system.runtime.serialization.primitives\4.3.0\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 4 | Copy-Item -Path $env:userprofile\.nuget\packages\newtonsoft.json\10.0.2\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 5 | Copy-Item -Path $env:userprofile\.nuget\packages\system.componentmodel.typeconverter\4.3.0\lib\netstandard1.5\* -Destination .\bin\Debug\netstandard1.3 6 | Copy-Item -Path $env:userprofile\.nuget\packages\system.collections.nongeneric\4.3.0\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 7 | Copy-Item -Path $env:userprofile\.nuget\packages\system.collections.specialized\4.3.0\lib\netstandard1.3\* -Destination .\bin\Debug\netstandard1.3 -------------------------------------------------------------------------------- /dotnetcore/simulated_ble/src/gw-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [ 3 | { 4 | "type": "dotnetcore", 5 | "name": "dotnetcore", 6 | "configuration": { 7 | "binding.path": "dotnetcore.dll", 8 | "binding.coreclrpath": "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\1.1.1\\coreclr.dll", 9 | "binding.trustedplatformassemblieslocation": "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\1.1.1\\" 10 | } 11 | } 12 | ], 13 | "modules": [ 14 | { 15 | "name": "simulated_device", 16 | "loader": { 17 | "name": "native", 18 | "entrypoint": { 19 | "module.path": "simulated_device.dll" 20 | } 21 | }, 22 | "args": { 23 | "macAddress": "01:02:03:03:02:01", 24 | "messagePeriod": 500 25 | } 26 | }, 27 | { 28 | "name": "ble_converter_module", 29 | "loader": { 30 | "name": "dotnetcore", 31 | "entrypoint": { 32 | "assembly.name": "IoTEdgeConverterModule", 33 | "entry.type": "IoTEdgeConverterModule.BleConverterModule" 34 | } 35 | }, 36 | "args": "" 37 | }, 38 | { 39 | "name": "printer_module", 40 | "loader": { 41 | "name": "dotnetcore", 42 | "entrypoint": { 43 | "assembly.name": "IoTEdgeConverterModule", 44 | "entry.type": "PrinterModule.DotNetPrinterModule" 45 | } 46 | }, 47 | "args": "" 48 | } 49 | ], 50 | "links": [ 51 | { 52 | "source": "simulated_device", "sink": "ble_converter_module" 53 | }, 54 | { 55 | "source": "ble_converter_module", "sink": "printer_module" 56 | } 57 | ] 58 | } -------------------------------------------------------------------------------- /images/Dotnet_properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/Dotnet_properties.png -------------------------------------------------------------------------------- /images/NetStandard_properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/NetStandard_properties.png -------------------------------------------------------------------------------- /images/VSCode_BuildTask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_BuildTask.png -------------------------------------------------------------------------------- /images/VSCode_BuildTaskRunner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_BuildTaskRunner.png -------------------------------------------------------------------------------- /images/VSCode_Config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_Config.png -------------------------------------------------------------------------------- /images/VSCode_Debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_Debug.png -------------------------------------------------------------------------------- /images/VSCode_EditCsproj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_EditCsproj.png -------------------------------------------------------------------------------- /images/VSCode_NewFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_NewFile.png -------------------------------------------------------------------------------- /images/VSCode_Rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_Rename.png -------------------------------------------------------------------------------- /images/VSCode_Restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_Restore.png -------------------------------------------------------------------------------- /images/VSCode_Run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_Run.png -------------------------------------------------------------------------------- /images/VSCode_SaveAs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_SaveAs.png -------------------------------------------------------------------------------- /images/VSCode_UpdateCsproj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/VSCode_UpdateCsproj.png -------------------------------------------------------------------------------- /images/dataflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/dataflow.png -------------------------------------------------------------------------------- /images/flow_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/iot-edge-samples/e28df71549603e1d160be7ae8b9489e8860a728a/images/flow_chart.png -------------------------------------------------------------------------------- /java/simulated_ble/README.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Edge BLE Data Converter Module with Java 2 | 3 | ## Overview 4 | 5 | This tutorial showcases how one might build a module for Azure IoT Edge in Java. 6 | 7 | In this tutorial, we will walk through environment setup and how to write a [BLE](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy) data converter module using the latest Azure IoT Edge Maven packages. 8 | 9 | ## Prerequisites 10 | 11 | In this section, you will setup your environment for IoT Edge module development. It applies to both *64-bit Windows* and *64-bit Linux (Ubuntu/Debian 8)* operating systems. 12 | 13 | The following software is required: 14 | 15 | 1. [Git Client](https://https://git-scm.com/downloads). 16 | 2. [**x64** JDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html). 17 | 3. [Maven](https://maven.apache.org/install.html). 18 | 19 | Open a command line terminal window and navigate to the working directory: 20 | 21 | 1. `git clone https://github.com/Azure-Samples/iot-edge-samples.git`. 22 | 2. `cd iot-edge-samples/java/simulated_ble` 23 | 24 | ## Overall Architecture 25 | 26 | The Azure IoT Edge platform heavily adopts the [Von Neumann architecture](https://en.wikipedia.org/wiki/Von_Neumann_architecture). Which means that the entire Azure IoT Edge architecture is a system which processes input and produces output; and that each individual module is also a tiny input-output subsystem. In this tutorial, we will introduce the following two modules: 27 | 28 | 1. A module which receives a simulated [BLE](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy) signal and converts it into a formatted [JSON](https://en.wikipedia.org/wiki/JSON) message. 29 | 2. A module which prints the received [JSON](https://en.wikipedia.org/wiki/JSON) message. 30 | 31 | The below image displays the typical end-to-end dataflow for this project: 32 | 33 | ![Dataflow between three modules](../../images/dataflow.png "Input: Simulated BLE Module; Processor: Converter Module; Output: Printer Module") 34 | 35 | ## Understanding the Code 36 | 37 | ### Maven Project Structure 38 | 39 | Since Azure IoT Edge packages are based on Maven, we need to create a typical Maven project structure, which contains a `pom.xml` file. 40 | 41 | Ths POM inherits from the `com.microsoft.azure.gateway.gateway-module-base` package which declares all of the dependencies needed by a module project which includes the runtime binaries, the gateway configuration file path, and the execution behavior. This will save us lots of time and eliminate the need to write and rewrite hundreds of lines of code over and over again. 42 | 43 | We need to update the pom.xml file by declaring the required dependencies/plugins and the name of the configuration file to be used by our module as shown in the code snippet below. 44 | 45 | ```xml 46 | 49 | 4.0.0 50 | 51 | 52 | 53 | com.microsoft.azure.gateway 54 | gateway-module-base 55 | 1.0.1 56 | 57 | 58 | com.microsoft.azure.gateway 59 | ble-converter 60 | 1.0 61 | jar 62 | 63 | 65 | 66 | gw-config.json 67 | 68 | 69 | 70 | 71 | 72 | com.microsoft.azure.gateway 73 | gateway-java-binding 74 | 75 | 76 | ${dependency.runtime.group} 77 | ${dependency.runtime.name} 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-dependency-plugin 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-resources-plugin 91 | 92 | 93 | org.apache.maven.plugins 94 | maven-shade-plugin 95 | 96 | 97 | org.codehaus.mojo 98 | exec-maven-plugin 99 | 100 | 101 | 102 | 103 | ``` 104 | 105 | ### Basic Understanding of an Azure IoT Edge Module 106 | 107 | You can treat an Azure IoT Edge module as a data processor whose job is to: receive input, process it, and produce output. 108 | 109 | The input might be data from hardware (like a motion detector), a message from other modules, or anything else (like a random number generated periodically by a timer). 110 | 111 | The output is similar to the input, it could trigger hardware behavior (like the blinking LED), a message to other modules, or anything else (like printing to the console). 112 | 113 | Modules communicate with each other using `com.microsoft.azure.gateway.messaging.Message` class. The **Content** of a `Message` is a byte array which is capable of representing any kind of data you like. **Properties** are also available in the `Message` and are simply a string-to-string mapping. You may think of **Properties** as the headers in a HTTP request, or the metadata of a file. 114 | 115 | In order to develop an Azure IoT Edge module in Java, you need to create a new module class which inherits from `com.microsoft.azure.gateway.core.GatewayModule` and implement the required abstract methods `receive()` and `destroy()`. At this point you may also choose to implement the optional `start()` or `create()` methods as well. The following code snippet shows you how to get started authoring an Azure IoT Edge module. 116 | 117 | ```java 118 | import com.microsoft.azure.gateway.core.Broker; 119 | import com.microsoft.azure.gateway.core.GatewayModule; 120 | import com.microsoft.azure.gateway.messaging.Message; 121 | 122 | public class MyEdgeModule extends GatewayModule { 123 | public MyEdgeModule(long address, Broker broker, String configuration) { 124 | /* Let the GatewayModule do the dirty work of initialization. It's also 125 | a good time to parse your own configuration defined in Azure IoT Edge 126 | configuration file (typically ./src/main/resources/gateway/gw-config.json) */ 127 | super(address, broker, configuration); 128 | } 129 | 130 | @Override 131 | public void start() { 132 | /* Acquire the resources you need. If you don't 133 | need any resources, you may omit this method. */ 134 | } 135 | 136 | @Override 137 | public void destroy() { 138 | /* It's time to release all resources. This method is required. */ 139 | } 140 | 141 | @Override 142 | public void receive(Message message) { 143 | /* Logic to process the input message. This method is required. */ 144 | // ... 145 | /* Use publish() method to do the output. You are 146 | allowed to publish your new Message instance. */ 147 | this.publish(message); 148 | } 149 | } 150 | ``` 151 | 152 | ### Converter Module 153 | 154 | | Input | Processor | Output | Source File | 155 | | ------------------------ | -------------------------------------- | ---------------------- | ---------------------- | 156 | | Temperature data message | Parse and construct a new JSON message | Structure JSON message | `ConverterModule.java` | 157 | 158 | This module is a typical Azure IoT Edge module. It accepts temperature messages from other modules (a hardware module, or in this case our simulated BLE module); and then normalizes the temperature message in to a structured JSON message (including appending the message ID, setting the property of whether we need to trigger the temperature alert, and so on). 159 | 160 | ```java 161 | @Override 162 | public void receive(Message message) { 163 | try { 164 | JSONObject messageFromBle = new JSONObject(new String(message.getContent())); 165 | double temperature = messageFromBle.getDouble("temperature"); 166 | Map inputProperties = message.getProperties(); 167 | 168 | HashMap properties = new HashMap<>(); 169 | properties.put("source", inputProperties.get("source")); 170 | properties.put("macAddress", inputProperties.get("macAddress")); 171 | properties.put("temperatureAlert", temperature > 30 ? "true" : "false"); 172 | 173 | String content = String.format( 174 | "{ \"deviceId\": \"Intel NUC Gateway\", \"messageId\": %d, \"temperature\": %f }", 175 | ++this.messageCount, temperature); 176 | 177 | this.publish(new Message(content.getBytes(), properties)); 178 | } catch (Exception ex) { 179 | ex.printStackTrace(); 180 | } 181 | } 182 | ``` 183 | 184 | ### Printer Module 185 | 186 | | Input | Processor | Output | Source File | 187 | | ------------------------------ | --------- | -------------------------- | -------------------- | 188 | | Any message from other modules | N/A | Log the message to console | `PrinterModule.java` | 189 | 190 | This is a very simple, self-explanatory, module which outputs the received messages to the terminal window. 191 | 192 | ```java 193 | @Override 194 | public void receive(Message message) { 195 | System.out.println(message.toString()); 196 | } 197 | ``` 198 | 199 | ### Azure IoT Edge Configuration 200 | 201 | The final step before running the modules is to configure the Azure IoT Edge and to establish the connections between modules. 202 | 203 | First we need to declare our Java loader (since Azure IoT Edge supports loaders of different languages) which could be referenced by its `name` in the sections afterward. 204 | 205 | ```json 206 | "loaders": [{ 207 | "type": "java", 208 | "name": "java", 209 | "configuration": { 210 | "jvm.options": { 211 | "library.path": "./" 212 | } 213 | } 214 | }] 215 | ``` 216 | 217 | Once we have declared our loaders we will also need to declare our modules as well. Similar to declaring the loaders, they can also be referenced by their `name` attribute. When declaring a module, we need to specify the loader it should use (which should be the one we defined before) and the entry-point (should be the normalized class name of our module) for each module. The `simulated_device` module is a native module which is included in the Azure IoT Edge core runtime package. You should always include `args` in the JSON file even if it is `null`. 218 | 219 | ```json 220 | "modules": [ 221 | { 222 | "name": "simulated_device", 223 | "loader": { 224 | "name": "native", 225 | "entrypoint": { 226 | "module.path": "simulated_device" 227 | } 228 | }, 229 | "args": { 230 | "macAddress": "01:02:03:03:02:01", 231 | "messagePeriod": 500 232 | } 233 | }, 234 | { 235 | "name": "converter", 236 | "loader": { 237 | "name": "java", 238 | "entrypoint": { 239 | "class.name": "com/microsoft/azure/gateway/ConverterModule", 240 | "class.path": "./ble-converter-1.0-with-deps.jar" 241 | } 242 | }, 243 | "args": null 244 | }, 245 | { 246 | "name": "print", 247 | "loader": { 248 | "name": "java", 249 | "entrypoint": { 250 | "class.name": "com/microsoft/azure/gateway/PrinterModule", 251 | "class.path": "./ble-converter-1.0-with-deps.jar" 252 | } 253 | }, 254 | "args": null 255 | } 256 | ] 257 | ``` 258 | 259 | At the end of the configuration, we establish the connections. Each connection is expressed by `source` and `sink`. They should both reference a pre-defined module. The output message of `source` module will be forwarded to the input of `sink` module. 260 | 261 | ```json 262 | "links": [ 263 | { 264 | "source": "simulated_device", 265 | "sink": "converter" 266 | }, 267 | { 268 | "source": "converter", 269 | "sink": "print" 270 | } 271 | ] 272 | ``` 273 | 274 | ## Running the Modules 275 | 276 | Use `mvn package` to build everything into the `target/` folder. `mvn clean package` is also recommended for a clean build. 277 | 278 | Use `mvn exec:exec` to run the Azure IoT Edge and you should observe that the temperature data and all the properties are printed to the console at a fixed rate. 279 | 280 | If you want to terminate the application, press `` key. 281 | 282 | > ⚠ It is not recommended to use Ctrl + C to terminate the IoT Edge gateway application. As this may cause the process to terminate abnormally. 283 | 284 | -------------------------------------------------------------------------------- /java/simulated_ble/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | 6 | com.microsoft.azure.gateway 7 | gateway-module-base 8 | 1.0.1 9 | 10 | 11 | com.microsoft.azure.gateway 12 | ble-converter 13 | 1.0 14 | jar 15 | 16 | 18 | 19 | gw-config.json 20 | 21 | 22 | 23 | 24 | 25 | com.microsoft.azure.gateway 26 | gateway-java-binding 27 | 28 | 29 | ${dependency.runtime.group} 30 | ${dependency.runtime.name} 31 | 32 | 33 | 34 | 35 | org.json 36 | json 37 | 20170516 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-dependency-plugin 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-resources-plugin 51 | 52 | 53 | org.apache.maven.plugins 54 | maven-shade-plugin 55 | 56 | 57 | org.codehaus.mojo 58 | exec-maven-plugin 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-compiler-plugin 65 | 3.6.1 66 | 67 | 1.8 68 | 1.8 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /java/simulated_ble/src/main/java/com/microsoft/azure/gateway/ConverterModule.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.azure.gateway; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.json.JSONObject; 7 | 8 | import com.microsoft.azure.gateway.core.Broker; 9 | import com.microsoft.azure.gateway.core.GatewayModule; 10 | import com.microsoft.azure.gateway.messaging.Message; 11 | 12 | public class ConverterModule extends GatewayModule { 13 | private int messageCount = 0; 14 | 15 | public ConverterModule(long address, Broker broker, String configuration) { 16 | super(address, broker, configuration); 17 | } 18 | 19 | @Override 20 | public void receive(Message message) { 21 | try { 22 | JSONObject messageFromBle = new JSONObject(new String(message.getContent())); 23 | double temperature = messageFromBle.getDouble("temperature"); 24 | Map inputProperties = message.getProperties(); 25 | 26 | HashMap properties = new HashMap<>(); 27 | properties.put("source", inputProperties.get("source")); 28 | properties.put("macAddress", inputProperties.get("macAddress")); 29 | properties.put("temperatureAlert", temperature > 30 ? "true" : "false"); 30 | 31 | String content = String.format( 32 | "{ \"deviceId\": \"Intel NUC Gateway\", \"messageId\": %d, \"temperature\": %f }", 33 | ++this.messageCount, temperature); 34 | 35 | this.publish(new Message(content.getBytes(), properties)); 36 | } catch (Exception ex) { 37 | ex.printStackTrace(); 38 | } 39 | } 40 | 41 | @Override 42 | public void destroy() { /* Nop. */ } 43 | } 44 | -------------------------------------------------------------------------------- /java/simulated_ble/src/main/java/com/microsoft/azure/gateway/PrinterModule.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.azure.gateway; 2 | 3 | import com.microsoft.azure.gateway.core.Broker; 4 | import com.microsoft.azure.gateway.core.GatewayModule; 5 | import com.microsoft.azure.gateway.messaging.Message; 6 | 7 | public class PrinterModule extends GatewayModule { 8 | public PrinterModule(long address, Broker broker, String configuration) { 9 | super(address, broker, configuration); 10 | } 11 | 12 | @Override 13 | public void receive(Message message) { 14 | System.out.println(message.toString()); 15 | System.out.println(); 16 | } 17 | 18 | @Override 19 | public void destroy() { /* Noop */ } 20 | } 21 | -------------------------------------------------------------------------------- /java/simulated_ble/src/main/resources/gateway/gw-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [{ 3 | "type": "java", 4 | "name": "java", 5 | "configuration": { 6 | "jvm.options": { 7 | "library.path": "./" 8 | } 9 | } 10 | }], 11 | "modules": [ 12 | { 13 | "name": "simulated_device", 14 | "loader": { 15 | "name": "native", 16 | "entrypoint": { 17 | "module.path": "simulated_device" 18 | } 19 | }, 20 | "args": { 21 | "macAddress": "01:02:03:03:02:01", 22 | "messagePeriod": 500 23 | } 24 | }, 25 | { 26 | "name": "converter", 27 | "loader": { 28 | "name": "java", 29 | "entrypoint": { 30 | "class.name": "com/microsoft/azure/gateway/ConverterModule", 31 | "class.path": "./ble-converter-1.0-with-deps.jar" 32 | } 33 | }, 34 | "args": null 35 | }, 36 | { 37 | "name": "print", 38 | "loader": { 39 | "name": "java", 40 | "entrypoint": { 41 | "class.name": "com/microsoft/azure/gateway/PrinterModule", 42 | "class.path": "./ble-converter-1.0-with-deps.jar" 43 | } 44 | }, 45 | "args": null 46 | } 47 | ], 48 | "links": [ 49 | { 50 | "source": "simulated_device", 51 | "sink": "converter" 52 | }, 53 | { 54 | "source": "converter", 55 | "sink": "print" 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /java/timer/README.md: -------------------------------------------------------------------------------- 1 | # Java Maven Package for Windows and Linux 2 | 3 | ## Overview 4 | 5 | This sample showcases how one might build a simple module for Azure IoT Edge in Java. 6 | 7 | The sample contains: 8 | 1. A `TimerModule.java` which will generate one message per second. It will also receive and print that message into the Console as well. 9 | 2. A `TimerModuleUnitTest.java` which will test the basic behavior of `TimerModule.java`. 10 | 3. A `gw-config.json` which is the runtime configuration file for the IoT Edge application. 11 | 4. A `pom.xml` which is used to declare all the dependencies, compiler version and execution stage for Maven. 12 | 13 | ## Prerequisites 14 | 15 | * The latest [JRE](http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html) (x86 on Windows; apt-get "default-jre" on Ubuntu) 16 | * [Maven](https://maven.apache.org/install.html) command line 17 | * **[Windows]** Add parent folder path of jvm.dll (might be "C:\Program Files (x86)\Java\jre1.8.0_121\bin\client") to the PATH environment variable 18 | 19 | ## The Data Flow 20 | There is only one module in this sample called `TimerModule`. Every second, it will publish to the IoT Edge a message containing the string representation of the current timestamp (i.e. `"Mon Mar 20 00:00:00 PDT 2017"`). This module also contains a `receive` method which will read the message from the IoT Edge, and print that message (both the content and the properties) to the Console. The configuration file `gw-config.json` specifies the only data flow of the IoT Edge: **ALL messages come from `TimerModule` will be received by `TimerModule` itself**. 21 | 22 | So in this case, a typical end-to-end dataflow is illustrated below: 23 | 24 | > ⟲ [*TimerModule*] Timer task kicks in every second
25 | → [*TimerModule*] Send current timestamp message to IoT Edge
26 | → [*IoT Edge*] Forward message according to `gw-config.json`
27 | → [*TimerModule*] Receive the message from IoT Edge
28 | → [*TimerModule*] Print out the message 29 | 30 | ## Running the sample 31 | 32 | To compile and run the sample, firstly you need to enter the `./azure-iot-gw-sample/java` folder use any command line tool you like on any platform. But please make sure that `mvn --version` works in that command line tool. 33 | 34 | Use "`mvn package`" to compile and pack the `TimerModule` into the `./target` folder. "`mvn clean package`" is recommended for a clean build. 35 | 36 | Use "`mvn exec:exec`" to run the IoT Edge gateway application and you should observe that every second a message will be printed out in the command line window. Please press `` key to terminate the IoT Edge gateway application gracefully. 37 | 38 | > ⚠ **DO NOT** use Ctrl+C to terminate the IoT Edge, it might cause some side-effects. 39 | 40 | ## Testing the sample 41 | 42 | Actually the test phase should already been invoked when you call the `mvn package` command. But still you could use "`mvn test`" or "`mvn clean test`" to run all the unit test cases. 43 | 44 | Basically the unit test of a module should test for the bahaviors of its input (`void receive(Message message)`) as well as its output (`void start()`); and this is what `TimerModuleUnitTest.java` does. It expects that each second a message will be generated and published to the IoT Edge; it also verifies that when a message is received by this module, that specific message will be printed out. 45 | 46 | ## Modifying the Code 47 | 48 | You could just change the code in `./src/main/java/com/microsoft/gateway/TimerModule.java`. But the `super(address, broker, configuration)` statement in the constructor should be preserved in order to let the IoT Edge successfully constructed. You can update the message to be sent in `void start()` method, and deal with the message you received in `void receive(Message message)` method. And remember to do the cleanup jobs in the `void destroy()` method if you create your own resources like new threads. 49 | 50 | > ⚠ Forgot to clean up the threads in `void destroy()` will not cause many problems if you are just need to terminate the IoT Edge, but it is not a good practice to do so. 51 | -------------------------------------------------------------------------------- /java/timer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | gw-config.json 4 | 5 | 6 | 7 | com.microsoft.azure.gateway 8 | gateway-module-base 9 | 1.0.1 10 | 11 | 4.0.0 12 | 13 | com.microsoft.gateway 14 | gateway-sample 15 | 1.0 16 | jar 17 | 18 | 19 | 20 | 21 | com.microsoft.azure.gateway 22 | gateway-java-binding 23 | 24 | 25 | ${dependency.runtime.group} 26 | ${dependency.runtime.name} 27 | 28 | 29 | 30 | 31 | junit 32 | junit 33 | 4.12 34 | test 35 | 36 | 37 | org.jmockit 38 | jmockit 39 | 1.8 40 | test 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-dependency-plugin 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-resources-plugin 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-shade-plugin 58 | 59 | 60 | org.codehaus.mojo 61 | exec-maven-plugin 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-compiler-plugin 68 | 3.6.1 69 | 70 | 1.8 71 | 1.8 72 | 73 | 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-surefire-plugin 79 | 2.19.1 80 | 81 | 82 | -Dfile.encoding=UTF-8 -javaagent:${settings.localRepository}/org/jmockit/jmockit/1.22/jmockit-1.22.jar 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /java/timer/src/main/java/com/microsoft/azure/gateway/TimerModule.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.azure.gateway; 2 | 3 | import java.util.*; 4 | import com.microsoft.azure.gateway.core.*; 5 | import com.microsoft.azure.gateway.messaging.*; 6 | 7 | public class TimerModule extends GatewayModule { 8 | public TimerModule(long address, Broker broker, String configuration) { 9 | super(address, broker, configuration); 10 | System.out.println("*************************************************"); 11 | System.out.println("** Timer Module Started, Press to Exit **"); 12 | System.out.println("*************************************************"); 13 | } 14 | 15 | @Override 16 | public void start() { 17 | new Timer(true).schedule(new TimerTask() { 18 | @Override 19 | public void run() { 20 | // This method will be called every second 21 | Message m = new Message(new Date().toString().getBytes(), null); 22 | try { 23 | TimerModule.this.publish(m); 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | }, 0, 1000); 29 | } 30 | 31 | @Override 32 | public void receive(Message message) { 33 | System.out.println(message.toString()); 34 | } 35 | 36 | @Override 37 | public void destroy() { 38 | // Since the time in start() is a daemon, the process will automatically 39 | // cancel it. Therefore we don't need to terminate the timer here. 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /java/timer/src/main/resources/gateway/gw-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [ 3 | { 4 | "type": "java", 5 | "name": "java", 6 | "configuration":{ 7 | "jvm.options":{ 8 | "library.path": "./" 9 | } 10 | } 11 | 12 | } 13 | ], 14 | "modules": [ 15 | { 16 | "name": "java_timer", 17 | "loader":{ 18 | "name": "java", 19 | "entrypoint": { 20 | "class.name": "com/microsoft/azure/gateway/TimerModule", 21 | "class.path": "./gateway-sample-1.0-with-deps.jar" 22 | } 23 | }, 24 | "args": null 25 | } 26 | ], 27 | "links": [ 28 | { 29 | "source": "java_timer", 30 | "sink": "java_timer" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /java/timer/src/test/java/com/microsoft/azure/gateway/TimerModuleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.azure.gateway; 2 | 3 | import java.io.*; 4 | import mockit.*; 5 | import org.junit.*; 6 | 7 | import com.microsoft.azure.gateway.core.*; 8 | import com.microsoft.azure.gateway.messaging.*; 9 | 10 | public class TimerModuleUnitTest { 11 | @Test 12 | public void shouldSendMessagePerSecond(@Mocked(stubOutClassInitialization = true) final Broker broker) throws IOException, InterruptedException { 13 | final TimerModule module = new TimerModule(0x1L, broker, null); 14 | new Expectations() {{ 15 | broker.publishMessage(withNotNull(), 0x1L); times = 3; 16 | }}; 17 | module.start(); 18 | Thread.sleep(2500); 19 | } 20 | 21 | @Test 22 | public void shouldPrintMessageWhenReceived(@Mocked final PrintStream out, @Mocked(stubOutClassInitialization = true) final Broker broker) { 23 | PrintStream originalOut = System.out; 24 | final TimerModule module = new TimerModule(0x1L, broker, null); 25 | Message testMessage = new Message("Test Message".getBytes(), null); 26 | System.setOut(out); 27 | module.receive(testMessage); 28 | new Verifications() {{ 29 | out.println(withEqual(testMessage.toString())); times = 1; 30 | }}; 31 | System.setOut(originalOut); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /js/converter/README.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Edge BLE Data Converter Module with NODEJS 2 | 3 | ## Overview 4 | 5 | This tutorial showcases how to create a module for Azure IoT Edge in JS. 6 | 7 | In this tutorial, we will walk through environment setup and how to write a [BLE](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy) data converter module using the latest Azure IoT Edge NPM packages. 8 | 9 | ## Prerequisites 10 | 11 | In this section, you will setup your environment for IoT Edge module development. It applies to both *64-bit Windows* and *64-bit Linux (Ubuntu 14+)* operating systems. 12 | 13 | The following software is required: 14 | 1. [Git Client](https://git-scm.com/downloads). 15 | 2. [Node LTS](https://nodejs.org). 16 | 3. `npm install -g yo`. 17 | 4. `npm install -g generator-az-iot-gw-module` 18 | 19 | ## Architecture 20 | 21 | The Azure IoT Edge platform heavily adopts the [Von Neumann architecture](https://en.wikipedia.org/wiki/Von_Neumann_architecture). Which means that the entire Azure IoT Edge architecture is a system which processes input and produces output; and that each individual module is also a tiny input-output subsystem. In this tutorial, we will introduce the following two modules: 22 | 23 | 1. A module which receives a simulated [BLE](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy) signal and converts it into a formatted [JSON](https://en.wikipedia.org/wiki/JSON) message. 24 | 2. A module which prints the received [JSON](https://en.wikipedia.org/wiki/JSON) message. 25 | 26 | The below image displays the typical end-to-end dataflow for this project: 27 | 28 | ![Dataflow between three modules](../../images/dataflow.png "Input: Simulated BLE Module; Processor: Converter Module; Output: Printer Module") 29 | 30 | ## Step-by-step 31 | Below we will show you how to quickly setup environment to start to write your first BLE converter module with JS. 32 | 33 | ### Create module project 34 | 1. Open a command-line window, run `yo az-iot-gw-module`. 35 | 2. Follow the steps on the screen to finish the initialization of your module project. 36 | 37 | ### Project structure 38 | A JS module project consists of the following components: 39 | 40 | `modules` - The customized JS module source files. Please replace the default `sensor.js` and `printer.js` with your own module files. 41 | 42 | `app.js` - The entry file to start the Edge instance. 43 | 44 | `gw.config.json` - The configuration file to customize the modules to be loaded by Edge. 45 | 46 | `package.json` - The metadata information for module project. 47 | 48 | `README.md` - The basic documentation for module project. 49 | 50 | 51 | ### Package File 52 | 53 | Ths `package.json` declares all the metadata information needed by a module project which includes the name, version, entry, scripts, runtime and development dependencies. 54 | 55 | Below code snippet shows how to configure for BLE converter sample project. 56 | ```json 57 | { 58 | "name": "converter", 59 | "version": "1.0.0", 60 | "description": "BLE data converter sample for Azure IoT Edge.", 61 | "repository": { 62 | "type": "git", 63 | "url": "https://github.com/Azure-Samples/iot-edge-samples" 64 | }, 65 | "main": "app.js", 66 | "scripts": { 67 | "start": "node app.js" 68 | }, 69 | "author": "Microsoft Corporation", 70 | "license": "MIT", 71 | "dependencies": { 72 | }, 73 | "devDependencies": { 74 | "azure-iot-gateway": "~1.1.3" 75 | } 76 | } 77 | ``` 78 | 79 | 80 | ### Entry File 81 | The `app.js` defines the way to initialize the edge instance. Here we don't need to make any change. 82 | 83 | ```javascript 84 | (function() { 85 | 'use strict'; 86 | 87 | const Gateway = require('azure-iot-gateway'); 88 | let config_path = './gw.config.json'; 89 | 90 | // node app.js 91 | if (process.argv.length < 2) { 92 | throw 'Calling pattern should be node app.js.'; 93 | } 94 | 95 | const gw = new Gateway(config_path); 96 | gw.run(); 97 | })(); 98 | ``` 99 | 100 | ### Interface of Module 101 | You can treat an Azure IoT Edge module as a data processor whose job is to: receive input, process it, and produce output. 102 | 103 | The input might be data from hardware (like a motion detector), a message from other modules, or anything else (like a random number generated periodically by a timer). 104 | 105 | The output is similar to the input, it could trigger hardware behavior (like the blinking LED), a message to other modules, or anything else (like printing to the console). 106 | 107 | Modules communicate with each other using `message` object. The **content** of a `message` is a byte array which is capable of representing any kind of data you like. **properties** are also available in the `message` and are simply a string-to-string mapping. You may think of **properties** as the headers in a HTTP request, or the metadata of a file. 108 | 109 | In order to develop an Azure IoT Edge module in JS, you need to create a new module object which implements the required methods `receive()`. At this point you may also choose to implement the optional `create()` or `start()`, or `destroy()` methods as well. The following code snippet shows you the scaffolding of JS module object. 110 | 111 | ```javascript 112 | 'use strict'; 113 | 114 | module.exports = { 115 | broker: null, 116 | configuration: null, 117 | 118 | create: function (broker, configuration) { 119 | // Default implementation. 120 | this.broker = broker; 121 | this.configuration = configuration; 122 | 123 | return true; 124 | }, 125 | 126 | start: function () { 127 | // Produce 128 | }, 129 | 130 | receive: function (message) { 131 | // Consume 132 | }, 133 | 134 | destroy: function () { 135 | } 136 | }; 137 | ``` 138 | 139 | ### Converter Module 140 | | Input | Processor | Output | Source File | 141 | | ------------------------ | -------------------------------------- | ---------------------- | ---------------------- | 142 | | Temperature data message | Parse and construct a new JSON message | Structure JSON message | `converter.js` | 143 | 144 | This module is a typical Azure IoT Edge module. It accepts temperature messages from other modules (a hardware module, or in this case our simulated BLE module); and then normalizes the temperature message in to a structured JSON message (including appending the message ID, setting the property of whether we need to trigger the temperature alert, and so on). 145 | 146 | ```javascript 147 | receive: function (message) { 148 | // Initialize the messageCount in global object at first time. 149 | if (!global.messageCount) { 150 | global.messageCount = 0; 151 | } 152 | 153 | // Read the content and properties objects from message. 154 | let rawContent = JSON.parse(Buffer.from(message.content).toString('utf8')); 155 | let rawProperties = message.properties; 156 | 157 | // Generate new properties object. 158 | let newProperties = { 159 | source: rawProperties.source, 160 | macAddress: rawProperties.macAddress, 161 | temperatureAlert: rawContent.temperature > 30 ? 'true' : 'false' 162 | }; 163 | 164 | // Generate new content object. 165 | let newContent = { 166 | deviceId: 'Intel NUC Gateway', 167 | messageId: ++global.messageCount, 168 | temperature: rawContent.temperature 169 | }; 170 | 171 | // Publish the new message to broker. 172 | this.broker.publish( 173 | { 174 | properties: newProperties, 175 | content: new Uint8Array(Buffer.from(JSON.stringify(newContent), 'utf8')) 176 | } 177 | ); 178 | }, 179 | ``` 180 | 181 | ### Printer Module 182 | | Input | Processor | Output | Source File | 183 | | ------------------------------ | --------- | -------------------------- | -------------------- | 184 | | Any message from other modules | N/A | Log the message to console | `printer.js` | 185 | 186 | This is a very simple, self-explanatory, module which outputs the received messages(property, content) to the terminal window. 187 | 188 | ```javascript 189 | receive: function (message) { 190 | let properties = JSON.stringify(message.properties); 191 | let content = Buffer.from(message.content).toString('utf8'); 192 | 193 | console.log(`printer.receive.properties - ${properties}`); 194 | console.log(`printer.receive.content - ${content}\n`); 195 | } 196 | ``` 197 | 198 | ### Configuration 199 | The final step before running the modules is to configure the Azure IoT Edge and to establish the connections between modules. 200 | 201 | First we need to declare our `node` loader (since Azure IoT Edge supports loaders of different languages) which could be referenced by its `name` in the sections afterward. 202 | 203 | ```json 204 | "loaders": [ 205 | { 206 | "type": "node", 207 | "name": "node" 208 | } 209 | ] 210 | ``` 211 | 212 | Once we have declared our loaders we will also need to declare our modules as well. Similar to declaring the loaders, they can also be referenced by their `name` attribute. When declaring a module, we need to specify the loader it should use (which should be the one we defined before) and the entry-point (should be the normalized class name of our module) for each module. The `simulated_device` module is a native module which is included in the Azure IoT Edge core runtime package. You should always include `args` in the JSON file even if it is `null`. 213 | 214 | ```json 215 | "modules": [ 216 | { 217 | "name": "simulated_device", 218 | "loader": { 219 | "name": "native", 220 | "entrypoint": { 221 | "module.path": "simulated_device" 222 | } 223 | }, 224 | "args": { 225 | "macAddress": "01:02:03:03:02:01", 226 | "messagePeriod": 500 227 | } 228 | }, 229 | { 230 | "name": "converter", 231 | "loader": { 232 | "name": "node", 233 | "entrypoint": { 234 | "main.path": "modules/converter.js" 235 | } 236 | }, 237 | "args": null 238 | }, 239 | { 240 | "name": "printer", 241 | "loader": { 242 | "name": "node", 243 | "entrypoint": { 244 | "main.path": "modules/printer.js" 245 | } 246 | }, 247 | "args": null 248 | } 249 | ] 250 | ``` 251 | 252 | At the end of the configuration, we establish the connections. Each connection is expressed by `source` and `sink`. They should both reference a pre-defined module. The output message of `source` module will be forwarded to the input of `sink` module. 253 | 254 | ```json 255 | "links": [ 256 | { 257 | "source": "simulated_device", 258 | "sink": "converter" 259 | }, 260 | { 261 | "source": "converter", 262 | "sink": "printer" 263 | } 264 | ] 265 | ``` 266 | 267 | ## Running the Modules 268 | 1. `npm install` 269 | 2. `npm start` 270 | 271 | If you want to terminate the application, press `` key. 272 | 273 | > ⚠ It is not recommended to use Ctrl + C to terminate the IoT Edge application. As this may cause the process to terminate abnormally. 274 | -------------------------------------------------------------------------------- /js/converter/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | const Gateway = require('azure-iot-gateway'); 5 | let config_path = './gw.config.json'; 6 | 7 | // node app.js 8 | if (process.argv.length < 2) { 9 | throw 'Calling pattern should be node app.js.'; 10 | } 11 | 12 | const gw = new Gateway(config_path); 13 | gw.run(); 14 | })(); 15 | -------------------------------------------------------------------------------- /js/converter/gw.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [ 3 | { 4 | "type": "node", 5 | "name": "node" 6 | } 7 | ], 8 | "modules": [ 9 | { 10 | "name": "simulated_device", 11 | "loader": { 12 | "name": "native", 13 | "entrypoint": { 14 | "module.path": "simulated_device" 15 | } 16 | }, 17 | "args": { 18 | "macAddress": "01:02:03:03:02:01", 19 | "messagePeriod": 500 20 | } 21 | }, 22 | { 23 | "name": "converter", 24 | "loader": { 25 | "name": "node", 26 | "entrypoint": { 27 | "main.path": "modules/converter.js" 28 | } 29 | }, 30 | "args": null 31 | }, 32 | { 33 | "name": "printer", 34 | "loader": { 35 | "name": "node", 36 | "entrypoint": { 37 | "main.path": "modules/printer.js" 38 | } 39 | }, 40 | "args": null 41 | } 42 | ], 43 | "links": [ 44 | { 45 | "source": "simulated_device", 46 | "sink": "converter" 47 | }, 48 | { 49 | "source": "converter", 50 | "sink": "printer" 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /js/converter/modules/converter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | broker: null, 5 | configuration: null, 6 | 7 | create: function (broker, configuration) { 8 | this.broker = broker; 9 | this.configuration = configuration; 10 | 11 | return true; 12 | }, 13 | 14 | receive: function (message) { 15 | // Initialize the messageCount in global object at first time. 16 | if (!global.messageCount) { 17 | global.messageCount = 0; 18 | } 19 | 20 | // Read the content and properties objects from message. 21 | let rawContent = JSON.parse(Buffer.from(message.content).toString('utf8')); 22 | let rawProperties = message.properties; 23 | 24 | // Generate new properties object. 25 | let newProperties = { 26 | source: rawProperties.source, 27 | macAddress: rawProperties.macAddress, 28 | temperatureAlert: rawContent.temperature > 30 ? 'true' : 'false' 29 | }; 30 | 31 | // Generate new content object. 32 | let newContent = { 33 | deviceId: 'Intel NUC Gateway', 34 | messageId: ++global.messageCount, 35 | temperature: rawContent.temperature 36 | }; 37 | 38 | // Publish the new message to broker. 39 | this.broker.publish( 40 | { 41 | properties: newProperties, 42 | content: new Uint8Array(Buffer.from(JSON.stringify(newContent), 'utf8')) 43 | } 44 | ); 45 | }, 46 | 47 | destroy: function () { 48 | console.log('converter.destroy'); 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /js/converter/modules/printer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | broker: null, 5 | configuration: null, 6 | 7 | create: function (broker, configuration) { 8 | this.broker = broker; 9 | this.configuration = configuration; 10 | 11 | return true; 12 | }, 13 | 14 | receive: function (message) { 15 | let properties = JSON.stringify(message.properties); 16 | let content = Buffer.from(message.content).toString('utf8'); 17 | 18 | console.log(`printer.receive.properties - ${properties}`); 19 | console.log(`printer.receive.content - ${content}\n`); 20 | }, 21 | 22 | destroy: function () { 23 | console.log('printer.destroy'); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /js/converter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "converter", 3 | "version": "1.0.0", 4 | "description": "BLE data converter sample for Azure IoT Edge.", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Azure-Samples/iot-edge-samples" 8 | }, 9 | "main": "app.js", 10 | "scripts": { 11 | "start": "node app.js" 12 | }, 13 | "author": "Microsoft Corporation", 14 | "license": "MIT", 15 | "dependencies": { 16 | }, 17 | "devDependencies": { 18 | "azure-iot-gateway": "~1.1.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /js/simple/README.md: -------------------------------------------------------------------------------- 1 | # Simple Azure IoT Edge Modules 2 | This sample simply shows: 3 | - How to write modules (sensor.js, printer.js, iothub_writer.js) in JavaScript. 4 | - How to customize the IoT Edge runtime (gw.[local|cloud].config.json). 5 | - How to initialize and start the IoT Edge application in JavaScript (app.js). 6 | 7 | # Technical Details 8 | ## Callbacks 9 | Each module (sensor/printer/iothub_writer) needs to implement callbacks for different events: 10 | 1. create - module is created 11 | 2. start - module starts 12 | 3. receive - receive message from broker 13 | 4. destroy - modules is destroyed 14 | ## Data pipeline 15 | The configuration JSON file (gw.[local|cloud].config.json) to initialize each IoT Edge instance will 16 | need to define the data links for different module pairs. 17 | ## Connect to Azure IoT Hub 18 | iothub_writer module shows you how to establish connection between IoT Edge application and Azure IoT Hub. Below are the steps to configure and run it: 19 | 1. Go to [Azure IoT Hub portal](https://azure.microsoft.com/en-us/services/iot-hub/) to create an 20 | IoT hub instance with your own Azure subscription account to connecte your IoT Edge application. 21 | 2. Update `gw.cloud.config.json` by replacing `` (in the 22 | `iothub_writer` module config JSON (*shown below*)) with your actual IoT Hub device connection 23 | string 24 | ``` 25 | { 26 | "name": "iothub_writer", 27 | "loader": { 28 | "name": "node", 29 | "entrypoint": { 30 | "main.path": "modules/iothub_writer.js" 31 | } 32 | }, 33 | "args": { 34 | "connection_string": "" 35 | } 36 | } 37 | ``` 38 | 3. `cd modules & npm install` 39 | 4. `cd .. & npm install` 40 | 5. `npm run cloud` 41 | -------------------------------------------------------------------------------- /js/simple/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | const Gateway = require('azure-iot-gateway'); 5 | let config_path = null; 6 | 7 | // node app.js [local | cloud ] 8 | if (process.argv.length < 3) { 9 | throw 'Calling pattern should be node app.js [local | cloud].'; 10 | } 11 | 12 | const option = process.argv[2]; 13 | 14 | if (option === 'local') { 15 | config_path = './gw.local.config.json'; 16 | } else if (option === 'cloud') { 17 | config_path = './gw.cloud.config.json'; 18 | } else { 19 | throw 'Invalid option to start app.js !'; 20 | } 21 | 22 | const gw = new Gateway(config_path); 23 | gw.run(); 24 | })(); 25 | -------------------------------------------------------------------------------- /js/simple/gw.cloud.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [ 3 | { 4 | "type": "node", 5 | "name": "node" 6 | } 7 | ], 8 | "modules": [ 9 | { 10 | "name": "node_sensor", 11 | "loader": { 12 | "name": "node", 13 | "entrypoint": { 14 | "main.path": "modules/sensor.js" 15 | } 16 | }, 17 | "args": null 18 | }, 19 | { 20 | "name": "node_printer", 21 | "loader": { 22 | "name": "node", 23 | "entrypoint": { 24 | "main.path": "modules/printer.js" 25 | } 26 | }, 27 | "args": null 28 | }, 29 | { 30 | "name": "iothub_writer", 31 | "loader": { 32 | "name": "node", 33 | "entrypoint": { 34 | "main.path": "modules/iothub_writer.js" 35 | } 36 | }, 37 | "args": { 38 | "connection_string": "" 39 | } 40 | } 41 | ], 42 | "links": [ 43 | { 44 | "source": "node_sensor", 45 | "sink": "node_printer" 46 | }, 47 | { 48 | "source": "node_sensor", 49 | "sink": "iothub_writer" 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /js/simple/gw.local.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loaders": [ 3 | { 4 | "type": "node", 5 | "name": "node" 6 | } 7 | ], 8 | "modules": [ 9 | { 10 | "name": "node_printer", 11 | "loader": { 12 | "name": "node", 13 | "entrypoint": { 14 | "main.path": "modules/printer.js" 15 | } 16 | }, 17 | "args": null 18 | }, 19 | { 20 | "name": "node_sensor", 21 | "loader": { 22 | "name": "node", 23 | "entrypoint": { 24 | "main.path": "modules/sensor.js" 25 | } 26 | }, 27 | "args": null 28 | } 29 | ], 30 | "links": [ 31 | { 32 | "source": "node_sensor", 33 | "sink": "node_printer" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /js/simple/modules/iothub_writer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let Protocol = require('azure-iot-device-amqp').Amqp; 4 | let Client = require('azure-iot-device').Client; 5 | let Message = require('azure-iot-device').Message; 6 | 7 | class IotHubWriterModule { 8 | constructor() { 9 | this.iothub_client = null; 10 | this.connected = false; 11 | } 12 | 13 | on_connect(err) { 14 | if (err) { 15 | console.error(`Could not connect to IoT Hub. Error: ${err.message}`); 16 | } else { 17 | this.connected = true; 18 | this.iothub_client.on('error', this.on_error.bind(this)); 19 | this.iothub_client.on('disconnect', this.on_disconnect.bind(this)); 20 | } 21 | } 22 | 23 | on_error(err) { 24 | console.error(`Azure IoT Hub error: ${err.message}`); 25 | } 26 | 27 | on_disconnect() { 28 | console.log('Got disconnected from Azure IoT Hub.'); 29 | this.connected = false; 30 | } 31 | 32 | create(broker, configuration) { 33 | this.broker = broker; 34 | this.configuration = configuration; 35 | 36 | if (this.configuration && this.configuration.connection_string) { 37 | // open a connection to the IoT Hub 38 | this.iothub_client = Client.fromConnectionString(this.configuration.connection_string, Protocol); 39 | this.iothub_client.open(this.on_connect.bind(this)); 40 | 41 | return true; 42 | } else { 43 | console.error('This module requires the connection string to be passed in via configuration.'); 44 | return false; 45 | } 46 | } 47 | 48 | receive(message) { 49 | if(message.content){ 50 | let data = Buffer.from(message.content).toString('utf8'); 51 | if (this.connected) { 52 | var m = new Message(data); 53 | if (message.properties) { 54 | for (var prop in message.properties) { 55 | m.properties.add(prop, message.properties[prop]); 56 | } 57 | } 58 | this.iothub_client.sendEvent(m, err => { 59 | if (err) { 60 | console.error(`An error occurred when sending message to Azure IoT Hub: ${err.toString()}`); 61 | } 62 | }); 63 | } 64 | } else { 65 | console.log('writer.receive - Empty Message.content.'); 66 | } 67 | } 68 | 69 | destroy() { 70 | console.log('iothub_writer.destroy'); 71 | if (this.connected) { 72 | this.iothub_client.close(err => { 73 | if (err) { 74 | console.error(`An error occurred when disconnecting from Azure IoT Hub: ${err.toString()}`); 75 | } 76 | }); 77 | } 78 | } 79 | } 80 | 81 | module.exports = new IotHubWriterModule(); 82 | -------------------------------------------------------------------------------- /js/simple/modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "iothub_writer.js", 6 | "author": "Microsoft", 7 | "license": "MIT", 8 | "dependencies": { 9 | "azure-iot-device": "^1.0.6", 10 | "azure-iot-device-amqp": "^1.0.6" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /js/simple/modules/printer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | broker: null, 5 | configuration: null, 6 | 7 | create: function (broker, configuration) { 8 | this.broker = broker; 9 | this.configuration = configuration; 10 | 11 | return true; 12 | }, 13 | 14 | receive: function (message) { 15 | let data = Buffer.from(message.content).toString('utf8'); 16 | 17 | console.log(`printer.receive - ${data}`); 18 | }, 19 | 20 | destroy: function () { 21 | console.log('printer.destroy'); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /js/simple/modules/sensor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | broker: null, 5 | configuration: null, 6 | 7 | create: function (broker, configuration) { 8 | this.broker = broker; 9 | this.configuration = configuration; 10 | 11 | return true; 12 | }, 13 | 14 | start: function () { 15 | setInterval(() => { 16 | let data = [{ 17 | name: 'input', 18 | content: [{ 19 | 'sensorId': 'device1', 20 | temp: this.rangeRand(10, 200), 21 | hmdt: this.rangeRand(0, 100) 22 | }, { 23 | 'sensorId': 'device2', 24 | temp: this.rangeRand(10, 200), 25 | hmdt: this.rangeRand(0, 100) 26 | }, { 27 | 'sensorId': 'device3', 28 | temp: this.rangeRand(10, 200), 29 | hmdt: this.rangeRand(0, 100) 30 | }] 31 | }]; 32 | 33 | this.broker.publish({ 34 | properties: { 35 | source: 'sensor', 36 | name: 'data' 37 | }, 38 | content: new Uint8Array(Buffer.from(JSON.stringify(data), 'utf8')) 39 | }); 40 | }, 500); 41 | }, 42 | 43 | rangeRand: function(min, max) { 44 | if (!Number.isInteger(min) || !Number.isInteger(max)) { 45 | console.error(`Please make sure ${min} and ${max} are integer.`); 46 | return; 47 | } 48 | 49 | return Math.floor(Math.random() * (max - min) + min); 50 | }, 51 | 52 | receive: function(message) { 53 | }, 54 | 55 | destroy: function() { 56 | console.log('sensor.destroy'); 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /js/simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple", 3 | "version": "1.0.0", 4 | "description": "Simple sensor and printer modules run on Azure IoT Edge.", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Azure-Samples/iot-edge-samples" 8 | }, 9 | "main": "app.js", 10 | "scripts": { 11 | "local": "node app.js local", 12 | "cloud": "node app.js cloud" 13 | }, 14 | "author": "Microsoft Corporation", 15 | "license": "MIT", 16 | "dependencies": { 17 | }, 18 | "devDependencies": { 19 | "azure-iot-gateway": "~1.1.4", 20 | "azure-iot-device-amqp": "~1.1.17" 21 | } 22 | } 23 | --------------------------------------------------------------------------------