├── .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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------