From f1fb5e785bf1bfb58a64984ceaadbf4c635ed273 Mon Sep 17 00:00:00 2001 From: Laurent Ellerbach Date: Thu, 18 Nov 2021 17:49:08 +0100 Subject: [PATCH] Add Markdownlint to improve Markdown produced quality (#1710) * Add markdown lint to the repository * adjusting pipeline * adjusting based on PR feedback --- .markdownlint.json | 3 + .vsts-ci.yml | 8 ++- Documentation/CONTRIBUTING.md | 16 ++--- Documentation/Devices-conventions.md | 4 +- Documentation/How-to-Deploy-an-IoT-App.md | 69 ++++++++----------- ...app-automatically-on-boot-using-systemd.md | 12 ++-- ...to-start-your-app-automatically-on-boot.md | 20 +++--- Documentation/README.md | 50 +++++++++++--- Documentation/creating-new-release.md | 14 ++-- Documentation/raspi-i2c.md | 2 +- Documentation/raspi-pwm.md | 10 +-- Documentation/raspi-spi.md | 24 +++---- Documentation/roadmap.md | 5 +- README.md | 6 +- SECURITY.md | 6 +- eng/common/README.md | 2 +- samples/Device Binding Template.md | 5 +- samples/README.md | 4 +- samples/bmp280-sensor-azure-iot-hub/Readme.md | 4 +- .../create-certificate.md | 5 +- samples/force-sensitive-resistor/README.md | 19 ++--- samples/led-blink-multiple/README.md | 2 +- samples/led-blink/README.md | 6 +- samples/led-more-blinking-lights/README.md | 4 +- samples/serialport-arduino/README.md | 15 ++-- src/devices/Bmm150/README.md | 4 +- src/devices/DCMotor/README.md | 2 +- src/devices/Device-Index.md | 2 + src/devices/Dhtxx/README.md | 12 ++-- src/devices/Gpio/README.md | 4 +- src/devices/Ip5306/README.md | 1 - src/devices/Mcp960x/README.md | 7 +- src/devices/Pcx857x/README.md | 2 +- src/devices/README.md | 2 + src/devices/Scd4x/README.md | 3 +- src/devices/Sht4x/README.md | 2 +- src/devices/UFireIse/README.md | 36 +++++----- tools/DevicesApiTester/README.md | 40 +++++++---- tools/GenerateDocFxStructure/README.md | 2 +- tools/device-listing/README.md | 1 - .../templates/DeviceBindingTemplate/README.md | 11 ++- .../README.md | 5 +- .../samples/README.md | 1 - 43 files changed, 251 insertions(+), 201 deletions(-) create mode 100644 .markdownlint.json diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000..73481319 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,3 @@ +{ + "MD013": false +} \ No newline at end of file diff --git a/.vsts-ci.yml b/.vsts-ci.yml index 80764170..9700cf59 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -100,6 +100,12 @@ stages: steps: - checkout: self clean: true + # Scan markdown files on style consistency + - powershell: | + npm install -g markdownlint-cli + markdownlint -c $(System.DefaultWorkingDirectory)/.markdownlint.json $(System.DefaultWorkingDirectory) + displayName: 'Execute Markdownlint' + # Use utility script to run script command dependent on agent OS. - script: build.cmd -ci -sign -configuration $(_BuildConfig) @@ -128,7 +134,7 @@ stages: artifactName: BuiltPackageOutputs artifactType: container condition: eq(variables['_BuildConfig'], 'Release') - + - job: Linux container: LinuxContainer pool: diff --git a/Documentation/CONTRIBUTING.md b/Documentation/CONTRIBUTING.md index 606f088d..a437e428 100644 --- a/Documentation/CONTRIBUTING.md +++ b/Documentation/CONTRIBUTING.md @@ -1,14 +1,13 @@ -How to Contribute -================= - -# Building IoT Repo +# How to Contribute ## Recommended Software + 1. (If building on Windows) - **[Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/)** (Community, Professional, Enterprise) with the latest updates. This is not required for building the repo, but it will help a lot if the intent is to change the code or add new bindings. 1. **.NET Core SDK** To ensure the install worked, make sure you can call `dotnet` tool from a command prompt. We now require .NET 6 preview versions of the SDKs because of our central infrastructure, you can find the installers per platform here: - - For Windows: [Link to .NET 6 preview installer for Windows](https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-rc.1.21430.12/dotnet-sdk-6.0.100-rc.1.21430.12-win-x64.exe) **This is important as you won't be able to open projects on Visual Studio if you don't install this machine-wide** - - For Linux: [Link to .NET 6 preview SDK for Linux](https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-rc.1.21430.12/dotnet-sdk-6.0.100-rc.1.21430.12-linux-x64.tar.gz) - - For OSX: [Link to .NET 6 preview SDK for OSX](https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-rc.1.21430.12/dotnet-sdk-6.0.100-rc.1.21430.12-osx-x64.tar.gz) + +- For Windows: [Link to .NET 6 preview installer for Windows](https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-rc.1.21430.12/dotnet-sdk-6.0.100-rc.1.21430.12-win-x64.exe) **This is important as you won't be able to open projects on Visual Studio if you don't install this machine-wide** +- For Linux: [Link to .NET 6 preview SDK for Linux](https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-rc.1.21430.12/dotnet-sdk-6.0.100-rc.1.21430.12-linux-x64.tar.gz) +- For OSX: [Link to .NET 6 preview SDK for OSX](https://dotnetcli.azureedge.net/dotnet/Sdk/6.0.100-rc.1.21430.12/dotnet-sdk-6.0.100-rc.1.21430.12-osx-x64.tar.gz) ## Building from the Command Line @@ -26,9 +25,8 @@ In order to be able to open and build most projects in the repo with Visual Stud When opening the main library project (System.Device.Gpio) in Visual Studio, you can select the right configuration depending if you want to build the Linux or the Windows Configuration: -![](images/configurations.png) +![configurations](images/configurations.png) It is worth noting that files which are specific to the Linux configuration of a project, will have a filename like `*.Linux.cs` while the ones that are specific to Windows would have it like `*.Windows.cs` instead. To work with individual bindings, each folder under `src/devices/` has a solution that includes all relevant projects for that binding, together with an example project using the binding and the unit tests (if any). These solutions are the preferred way of working with individual bindings. - diff --git a/Documentation/Devices-conventions.md b/Documentation/Devices-conventions.md index d17c926d..6ffb4f89 100644 --- a/Documentation/Devices-conventions.md +++ b/Documentation/Devices-conventions.md @@ -28,11 +28,11 @@ There is no specific guidelines what simple and main scenario is but you should - Integer values (i.e. pin number) should use `-1` as invalid/unassigned value (as opposed to `null` and `Nullable`) - If your device has internal register create an enum for the addresses (i.e. `enum Register : byte`) -`*` - Vector3 is currently backed by float, this may be changed in the future: https://github.com/dotnet/corefx/issues/25334 +`*` - Vector3 is currently backed by float, this may be changed in the future: ## Units -Use [UnitsNet](https://github.com/angularsen/UnitsNet) whenever it is possible on any public functions, event or properties. This supports a lot of different types of units. +Use [UnitsNet](https://github.com/angularsen/UnitsNet) whenever it is possible on any public functions, event or properties. This supports a lot of different types of units. If your sensor/binding unit is not present in UnitsNet, then most common case units should match [International System of Units (aka. SI)](https://en.wikipedia.org/wiki/International_System_of_Units). diff --git a/Documentation/How-to-Deploy-an-IoT-App.md b/Documentation/How-to-Deploy-an-IoT-App.md index 6f206734..80ea8857 100644 --- a/Documentation/How-to-Deploy-an-IoT-App.md +++ b/Documentation/How-to-Deploy-an-IoT-App.md @@ -2,69 +2,59 @@ This provides information how to prepare a Publish Profile and deploy an application to a development board. -### Using Visual Studio +## Using Visual Studio 1. Once you have an application setup in Visual Studio, right-click the project in the Solution Explorer and select Publish... - 2. In the Pick a publish target dialog, select Folder, choose a folder to publish your application files and click Create Profile. The example below shows a path of C:\PublishedApps. - 3. A default profile, FolderProfile.pubxml, will now be created and added to your project. You can view it in the Solution Explorer under your project > Properties > PublishProfiles folder. - 4. It is a good practice to rename your profile to something you can relate with your project. In the Publish Window, click the Actions dropdown and select Rename Profile. A Rename Profile dialog prompts you to rename your profile. Click Save after renaming. - -5. You can configure the profile's settings by clicking Configure... in the Publish Window. A Profile Settings dialog prompt includes a few options. - - **Notes** +5. You can configure the profile's settings by clicking Configure... in the Publish Window. A Profile Settings dialog prompt includes a few options. **Notes**: * Prior to Visual Studio 2019, the Target Runtime doesn't offer a selection for Linux ARM or Windows ARM. When using an older version of Visual Studio, you will need to manually open the profile's XML and change the RuntimeIdentifier element to **linux-arm** or **win-arm** shown below: - ``` + ```csharp linux-arm or.. win-arm or both.. linux-arm;win-arm ``` - + * Deployment Mode Options: * **Framework Dependent** - App relies on the presence of a shared system-wide version of .NET Core on the target system. This will create a smaller size package. * **Self-contained** - .NET Core and required libraries will be bundled with your application creating a larger size package. IoT devices are usually constrained by memory resources. There is a useful NuGet package available that helps trim unused files. Reference [Microsoft.Packaging.Tools.Trimming](https://www.nuget.org/packages/Microsoft.Packaging.Tools.Trimming/) for more information. - - - * While there are more options available that can be modified, this only shows the basics. It is recommended to read more in the provided **References** section below. - -6. You can view the contents by double-clicking the profile. The contents should look similar to the XML below after your modifications. - -```xml - - - - FileSystem - Release - Any CPU - netcoreapp2.1 - C:\PublishedApps - linux-arm - true - <_IsPortable>false - - -``` + * While there are more options available that can be modified, this only shows the basics. It is recommended to read more in the provided **References** section below. +6. You can view the contents by double-clicking the profile. The content should look similar to the XML below after your modifications. + * Example: + + ```xml + + + + FileSystem + Release + Any CPU + netcoreapp2.1 + C:\PublishedApps + linux-arm + true + <_IsPortable>false + + + ``` 7. You can now publish your application by clicking Publish in the Publish Window. All folders/files should now be packaged in the specified publish folder. - 8. Your application is now ready for deployment to the target device. -### Using .NET Core CLI +## Using .NET Core CLI 1. Once you have an application setup, navigate to the directory where the project is located and run the `dotnet publish` command. Below shows a few common options and example. - * -c defines the build configuration (Debug or Release). * -o specifies the output path where application will be packaged. * -r publishes the application for given runtime (e.g. linux-arm, win-arm, etc.) being targeted. - ``` - dotnet publish -c Release -o C:\DeviceApiTester -r linux-arm - ``` + ```shell + dotnet publish -c Release -o C:\DeviceApiTester -r linux-arm + ``` 2. Your application is now ready for deployment to the target device. @@ -73,10 +63,11 @@ This provides information how to prepare a Publish Profile and deploy an applica The application can be deployed to a target device once the Publish Profile and related files have been packaged. There are various tools for transferring files depending on the platform being used. Below are a few popular tools available. * [PuTTy](https://www.putty.org/) -* PSCP (provided with PuTTy install) +* PSCP (provided with PuTTy install) * [FileZilla](https://filezilla-project.org/) ## References + * [Have Your Pi and Eat It Too: .NET Core 2.1 on Raspberry Pi](https://channel9.msdn.com/Events/dotnetConf/2018/S314) * [Visual Studio publish profiles for ASP.NET Core app deployment](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/visual-studio-publish-profiles?view=aspnetcore-2.2) * [Deploy an app to a local folder using Visual Studio](https://docs.microsoft.com/en-us/visualstudio/deployment/quickstart-deploy-to-local-folder?view=vs-2017) @@ -84,4 +75,4 @@ The application can be deployed to a target device once the Publish Profile and * [How to: Edit Deployment Settings in Publish Profile (.pubxml) Files and the .wpp.targets File in Visual Studio Web Projects](https://go.microsoft.com/fwlink/?LinkID=208121) * [.NET Core application deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/) * [dotnet publish](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21) -* [.NET Core RID Catalog](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog) \ No newline at end of file +* [.NET Core RID Catalog](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog) diff --git a/Documentation/How-to-start-your-app-automatically-on-boot-using-systemd.md b/Documentation/How-to-start-your-app-automatically-on-boot-using-systemd.md index 3d0b895f..9fd5d815 100644 --- a/Documentation/How-to-start-your-app-automatically-on-boot-using-systemd.md +++ b/Documentation/How-to-start-your-app-automatically-on-boot-using-systemd.md @@ -19,12 +19,11 @@ Make sure to make your app `````` is executable by using the command: chmod +x ``` - ## Create systemd.service unit For this example a script titled `.service` will be used. The folder that this application is ran from is `/home/pi/myiotappfolder` Please replace accordingly with your app name or the location you decide to save your script. Remember to add the `.service` as the file extension -Here is an example systemd.service file that you can use as a template. Make sure to use a Unix end of line when creating the systemmd.service file. +Here is an example systemd.service file that you can use as a template. Make sure to use a Unix end of line when creating the systemmd.service file. ```shell [Unit] @@ -61,6 +60,7 @@ Restart=always WantedBy=multi-user.target ``` + The systemmd service file which we will call `.service` must be saved to `/etc/systemd/system` to be ran on boot. Note that you must have admin priviliges to save a file to the system etc folder. You can use the following to copy the service in a terminal to this folder: @@ -78,19 +78,19 @@ chmod +x .service ``` ### Notes + Please use care and refer to the manual when using this code You may also look at the other scripts under /etc/systemd/system for reference. - - ## Test your service -This will start the service but will not run it on boot. +This will start the service but will not run it on boot. ```shell # Requires root permissions systemctl start .service ``` + Now you can look at the log file you created to see the output of the terminal. `/home/pi/myiotapp.log` Or you can check the status of the service by using in a terminal: @@ -107,7 +107,6 @@ To stop the service run: systemctl stop .service ``` - ## To make your service automatically run on boot ```shell @@ -126,7 +125,6 @@ Run this in terminal to disable the program on boot: systemctl disable myscript.service ``` - ## Security considerations Your app will be running with root permissions. diff --git a/Documentation/How-to-start-your-app-automatically-on-boot.md b/Documentation/How-to-start-your-app-automatically-on-boot.md index 9f6d8464..e3518982 100644 --- a/Documentation/How-to-start-your-app-automatically-on-boot.md +++ b/Documentation/How-to-start-your-app-automatically-on-boot.md @@ -4,7 +4,7 @@ For the purpose of this document let's assume you have deployed your app under: -``` +```shell /home/pi/myiotapp/myiotapp ``` @@ -16,7 +16,7 @@ Example script. `myiotapp` will be used everywhere. Please replace accordingly w File path should be `/etc/init.d/myiotapp` (note no extension - it may be used but it will become part of the name) -**Please make sure to read comments in the code below** +> **Important**: Please make sure to read comments in the code below ```shell #! /bin/sh @@ -42,20 +42,20 @@ case "$1" in # If you really need console capabilities you may also start your app under tmux # and connect to the app later using tmux attach - # tmux new-session -d -s myiotapp - # tmux send-keys '/home/pi/myiotapp/myiotapp' 'C-m' + # tmux new-session -d -s myiotapp + # tmux send-keys '/home/pi/myiotapp/myiotapp' 'C-m' # You may run multiple apps here - ;; + ;; stop) # This is not strictly required - can be commented out or removed # You may also provide more sophisticated way of disabling your app - killall myiotapp - ;; + killall myiotapp + ;; *) - echo "Usage: /etc/init.d/myiotapp {start|stop}" - exit 1 - ;; + echo "Usage: /etc/init.d/myiotapp {start|stop}" + exit 1 + ;; esac exit 0 diff --git a/Documentation/README.md b/Documentation/README.md index 90e1c6ba..d99c938f 100644 --- a/Documentation/README.md +++ b/Documentation/README.md @@ -1,4 +1,5 @@ # Resources + See the following resources to get started. ## Repo Layout @@ -14,27 +15,34 @@ This repository mainly contains two different components: * [DevicesApiTester CLI](https://github.com/dotnet/iot/tree/main/tools/DevicesApiTester) - Helpful utility, based on System.Device.* APIs, that include various commands for testing connected development boards and external hardware. ### Design Reviews + * [.NET Design Reviews: GPIO (10/2/2018)](https://youtu.be/OK0jDe8wtyg) * [.NET Design Reviews: GPIO (10/19/2018)](https://youtu.be/wtkPtOpI3CA) * [.NET Design Reviews: GPIO (11/2/2018)](https://youtu.be/UZc3sbJ0-PI) ### Showcase + [Mono WinForms GPIO Demo Using Toradex Colibri iMX7D and Torizon Container](https://www.youtube.com/watch?v=1d3g2VDZyXE) ## Interface Knowledge Base + ### General-Purpose Input/Output (GPIO) + * [GPIO Wiki](https://en.wikipedia.org/wiki/General-purpose_input/output) * [Digital I/O Fundamentals](http://www.ni.com/white-paper/3405/en/#toc1) ### Inter-Integrated Circuit (I2C) + * [I2C Wiki](https://en.wikipedia.org/wiki/I%C2%B2C) * [I2C Tutorial](https://learn.sparkfun.com/tutorials/i2c/all) ### Serial Peripheral Interface (SPI) + * [SPI Wiki](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface) * [SPI Tutorial](https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all) ## Other Helpful links + * [Configuring Remote Debugging from Dev machine to Raspberry Pi on ARM](https://www.hanselman.com/blog/RemoteDebuggingWithVSCodeOnWindowsToARaspberryPiUsingNETCoreOnARM.aspx) * [.NET Core Documentation](https://docs.microsoft.com/dotnet/) * [Install .NET Core on Raspberry Pi](https://github.com/dotnet/core/blob/master/samples/RaspberryPiInstructions.md) @@ -43,17 +51,21 @@ This repository mainly contains two different components: * [How to Prepare a Publish Profile](How-to-Deploy-an-IoT-App.md) ## Development Boards -**NOTE**: It has been verified that .NET Core will work on the following development boards. However, there has only been limited testing so far. It is recommended you experiment with the Raspberry Pi 3 and HummingBoard for now. + +> **NOTE**: It has been verified that .NET Core will work on the following development boards. However, there has only been limited testing so far. It is recommended you experiment with the Raspberry Pi 3 and HummingBoard for now. ### Raspberry Pi -#### General + +#### General information for Raspberry Pi + * [Raspberry Pi Website](https://www.raspberrypi.org/) * [Raspberry Pi GitHub Website](https://github.com/raspberrypi) * [Raspberry Pi Wiki](https://en.wikipedia.org/wiki/Raspberry_Pi) * [Raspberry Pi GPIO Pinout](https://learn.sparkfun.com/tutorials/raspberry-gpio/gpio-pinout) * [Raspberry Pi GPIO Tutorial](https://learn.sparkfun.com/tutorials/raspberry-gpio/all) -#### How-Tos +#### How-Tos for Raspberry Pi + * [Enable SPI on Raspberry Pi](./raspi-spi.md) * [Enable I2C on Raspberry Pi](./raspi-i2c.md) * [Enable Hardware PWM on Raspberry Pi](./raspi-pwm.md) @@ -61,57 +73,73 @@ This repository mainly contains two different components: * [Docker Access to Raspberry Pi GPIO Pins](https://stackoverflow.com/questions/30059784/docker-access-to-raspberry-pi-gpio-pins) * [Design a Raspberry Pi Hat in 10 Minutes](https://www.youtube.com/watch?v=1P7GOLFCCgs) -#### Products +#### Product details for Raspberry Pi + * [Raspberry Pi 3 Model B+](https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/) ### HummingBoard -#### General + +#### General information for HummingBoard + * [SolidRun Website](https://www.solid-run.com/) * [SolidRun GitHub Website](https://github.com/SolidRun) -#### Products +#### Product details for HummingBoard + * [HummingBoard](https://www.solid-run.com/nxp-family/hummingboard/) ### BeagleBoard -#### General + +#### General information for BeagleBoard + * [BeagleBoard Website](https://beagleboard.org/bone) * [BeagleBoard GitHub Website](https://github.com/beagleboard) * [BeagleBoard Wiki](https://en.wikipedia.org/wiki/BeagleBoard) -#### How-Tos +#### How-Tos for BeagleBoard + * [Example of .NET Core on a BBB](https://github.com/Redouane64/beaglebone-dotnet/tree/master/Examples/LEDBlink) -#### Products +#### Product details for BeagleBoard + * [BeagleBone Black (BBB)](https://beagleboard.org/black) * [BeagleBone Green (BBG)](https://beagleboard.org/green) ### Pine64 -#### General + +#### General information for Pine64 + * [Pine64 Website](https://www.pine64.org/) -#### Products +#### Product details for Pine64 + * [PINE A64-LTS](https://www.pine64.org/?page_id=46823) ## Maker Resources ### Prototyping + #### How-Tos + * [Blinking LED Blog Post by Scott Hanselman](https://www.hanselman.com/blog/InstallingTheNETCore2xSDKOnARaspberryPiAndBlinkingAnLEDWithSystemDeviceGpio.aspx) * [Collin's Lab: Breadboards & Perfboards](https://www.youtube.com/watch?v=w0c3t0fJhXU) * [How to Use a Breadboard](https://www.youtube.com/watch?v=6WReFkfrUIk) #### Software + * [Autodesk EAGLE PCB Designing Software](https://www.autodesk.com/products/eagle/free-download) * [FreeCAD](https://www.freecadweb.org/downloads.php) * [Fritzing](http://fritzing.org/home/) * [KiCad EDA](http://kicad.org/) ### Social + * [Hackaday.io](https://hackaday.io/) * [hackster.io](https://www.hackster.io/) * [instructables](https://www.instructables.com/) ### Vendors + * [Adafruit](https://www.adafruit.com/) * [CanaKit](https://www.canakit.com/) * [Digikey](https://www.digikey.com/) diff --git a/Documentation/creating-new-release.md b/Documentation/creating-new-release.md index 988bba3b..0d78d39b 100644 --- a/Documentation/creating-new-release.md +++ b/Documentation/creating-new-release.md @@ -2,19 +2,19 @@ This is a list of steps which need to happen in order to release new version of .NET IoT. -**This document is meant only for maintainers as special permissions might be required** +> **Note**: This document is meant only for maintainers as special permissions might be required ## Steps - Step 1: Ensure all PRs meant for this release are merged. - While the process is ongoing, make sure no new PRs get merged in order to ensure that the official build doesn't get reset. - Step 2: Regenerate device listing: - - `dotnet run` on https://github.com/dotnet/iot/tree/master/tools/device-listing + - `dotnet run` on - Fix all warnings, re-run if needed to ensure no warnings. - Always manually review the changes paying attention the generated document looks clear. - Adjust categories/code of the generator if necessary. - Step 3: Create new package: - - Go to https://dev.azure.com/dnceng/internal/_build?definitionId=239 + - Go to - Select "Run Pipeline", select row which says `variables` and add new one: `DotNetFinalVersionKind=release` (no quotes anywhere). - Run and wait for it to finish. - Once it is done and passes go to the artifacts section of the build, and find an artifact called 'Built packages' and from there download the two stable packages. @@ -24,19 +24,19 @@ This is a list of steps which need to happen in order to release new version of - Use `git tag -a ` to locally create a tag. - Use `git push origin ` to push it (`` is i.e. `1.3`). - Step 6: Edit release notes on github: - - Follow example: https://github.com/dotnet/iot/releases/tag/1.2 + - Follow example: - Copy the list of commits, clean those related to dependencies update. - - Use i.e.: https://github.com/dotnet/iot/compare/1.1...1.2 to see list of commits. + - Use i.e.: to see list of commits. - Categorize them by: `System.Gpio`, `Iot.Device.Bindings`, `Other` changes. - Rephrase/group them for consistency. - Add the list of contributors ordered by the number of commits or alphabetically. Command: `git shortlog -s 1.4..1.5` is very helpful but doesn't give github user names -- Step 7: After package is pushed to Nuget create a PR similar to https://github.com/dotnet/iot/pull/1310 to prepare for next release. +- Step 7: After package is pushed to Nuget create a PR similar to to prepare for next release. - Step 8: Update dependencies on old version of the package: - Option 1: Wait for `dependabot` to automatically create dependencies update PR (similar to: [System.Device.Gpio](https://github.com/dotnet/iot/pulls?q=is%3Apr+Bump+System.Device.Gpio+is%3Aclosed+author%3Aapp%2Fdependabot); [Iot.Device.Bindings](https://github.com/dotnet/iot/pulls?q=is%3Apr+Bump+Iot.Device.Bindings+is%3Aclosed+author%3Aapp%2Fdependabot)) - Options 2: Alternatively update versions manually to avoid swarm of PRs. - See list of PRs created by bot in the last release, search for old version across the repo and create a single PR doing all these changes combined. - Step 9: Update the documentation: - - Link to repository: https://github.com/dotnet/iot-api-docs + - Link to repository: - Currently this is not done by us, you will need to respond to the e-mail thread with request to update the documentation. - E-mail thread title for reference: `System.Device.Gpio and Iot.Device.Bindings in the .NET API browser`. - Contributors on the thread: @krwq @joperezr @richlander diff --git a/Documentation/raspi-i2c.md b/Documentation/raspi-i2c.md index 0dd65367..fa64cdf9 100644 --- a/Documentation/raspi-i2c.md +++ b/Documentation/raspi-i2c.md @@ -115,7 +115,7 @@ Following are only available on BCM2711. You can as well add `,baudrate=10000` f ### Adding your user to the right permission group -If you're running, or just upgraded to a version published after August 2020, this should be already done. +If you're running, or just upgraded to a version published after August 2020, this should be already done. But in case, you can always check that there are the right permissions on I2C: ```bash diff --git a/Documentation/raspi-pwm.md b/Documentation/raspi-pwm.md index 14dbbf72..5f088316 100644 --- a/Documentation/raspi-pwm.md +++ b/Documentation/raspi-pwm.md @@ -31,7 +31,7 @@ When you run the code, if you attached a simple led and a resistor on the physic If you get an error message like this one, it means the hardware PWM has not been properly enabled: -``` +```text Hello PWM! Unhandled exception. System.ArgumentException: The chip number 0 is invalid or is not enabled. at System.Device.Pwm.Channels.UnixPwmChannel.Validate() @@ -43,7 +43,7 @@ Aborted If you get an error message like the following one, it means that you don't have the permission, see the specific section below for this as well: -``` +```text Unhandled exception. System.UnauthorizedAccessException: Access to the path '/sys/class/pwm/pwmchip0/export' is denied. ---> System.IO.IOException: Permission denied ``` @@ -126,7 +126,7 @@ You are all setup, the basic example should now work with the PWM and channel yo When running the basic code, you may have a lack of permissions: -``` +```text Unhandled exception. System.UnauthorizedAccessException: Access to the path '/sys/class/pwm/pwmchip0/export' is denied. ---> System.IO.IOException: Permission denied --- End of inner exception stack trace --- @@ -156,7 +156,7 @@ sudo ./yourapplication ### Adding your user to the right permission group -If you're running, or just upgraded to a version published after August 2020, this should be already done. +If you're running, or just upgraded to a version published after August 2020, this should be already done. You will have to create a [specific group in udev](https://raspberrypi.stackexchange.com/questions/66890/accessing-pwm-module-without-root-permissions). ```bash @@ -165,7 +165,7 @@ sudo nano /etc/udev/rules.d/99-com.rules Add the following lines: -``` +```text SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\ chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\ chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\ diff --git a/Documentation/raspi-spi.md b/Documentation/raspi-spi.md index 5aba4b95..42b55bc8 100644 --- a/Documentation/raspi-spi.md +++ b/Documentation/raspi-spi.md @@ -2,7 +2,7 @@ In most of the cases, it is easy and straight forward to enable SPI for your Raspberry Pi. The basic case can be [found here](https://www.raspberrypi-spy.co.uk/2014/08/enabling-the-spi-interface-on-the-raspberry-pi/). -This page will explain how to setup any SPI. Please refer to the [Raspberry Pi documentation](https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/) to understand the different SPI available. You should be aware as well that for Raspberry Pi4, some of the configurations are different than for the other version especially for SPI3, 4 and 5. +This page will explain how to setup any SPI. Please refer to the [Raspberry Pi documentation](https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/) to understand the different SPI available. You should be aware as well that for Raspberry Pi4, some of the configurations are different than for the other version especially for SPI3, 4 and 5. ## Basic Hardware SPI usage @@ -26,11 +26,11 @@ namespace TestTest } ``` -This will open SPI0, with the default Chip Select. It will then write a byte to the MOSI pin and read 1 byte from the MISO pin. +This will open SPI0, with the default Chip Select. It will then write a byte to the MOSI pin and read 1 byte from the MISO pin. If you get something like this, it means you need to check the next sections to activate your SPI0: -``` +```text Unhandled exception. System.IO.IOException: Error 2. Can not open SPI device file '/dev/spidev0.0'. at System.Device.Spi.UnixSpiDevice.Initialize() at System.Device.Spi.UnixSpiDevice.WriteByte(Byte value) @@ -46,7 +46,7 @@ In very short, this is the line you'll need to add into the `/boot/config.txt` f sudo nano /boot/config.txt ``` -Add the line: +Add the line: ```text dtparam=spi=on @@ -76,11 +76,11 @@ In order to activate Chip Select, you'll need to add a specific dtoverlay on th Here is the table with the different options for SP0 and SP1 (please refer to the [Raspberry Pi documentation](https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/) to activate other SPI) -# SPI0 +## SPI0 The following dtoverlay definition can be [found here](https://github.com/raspberrypi/firmware/blob/7b99da75f55a5ad7d572ec4ebe4e8f9573deaee7/boot/overlays/README#L2437). -| SPI # | Chip Select # | Header Pin | Default GPIO | Pin Name | +| SPI # | Chip Select # | Header Pin | Default GPIO | Pin Name | | --- | --- | --- | --- | --- | | SPI0 | CE0 | 24 | GPIO08 | SPI0_CE0_N | | SPI0 | CE1 | 26 | GPIO07 | SPI0_CE1_N | @@ -99,9 +99,9 @@ dtoverlay=spi0-1cs,cs0_pin=27,no_miso There is only for SPI0 that you can use, in both cases with 1 or 2 Chip Select pin the `no_miso`option. -**Important note**: Those overlays are only supported in the very last Raspberry Pi OS. You will get the `System.IO.IOException: Error 2. Can not open SPI device file '/dev/spidev0.0'` error message if you are using them on an older version. You can use `spi0-cs` where in the previous examples you had `spi0-2cs` or `spi0-1cs`. +> **Important note**: Those overlays are only supported in the very last Raspberry Pi OS. You will get the `System.IO.IOException: Error 2. Can not open SPI device file '/dev/spidev0.0'` error message if you are using them on an older version. You can use `spi0-cs` where in the previous examples you had `spi0-2cs` or `spi0-1cs`. -As an alternative, you can as well use the following command line: `sudo raspi-config nonint do_spi 0 ` +As an alternative, you can as well use the following command line: `sudo raspi-config nonint do_spi 0` So the first example will now give: @@ -111,9 +111,9 @@ dtoverlay=spi0-cs,cs0_pin=27,cs1_pin=22 In older version, no_miso is not supported neither. And you will always get 2 chip select activated and you don't have a way to only select one. -# SPI1 to SPI6 +## SPI1 to SPI6 -The following dtoverlay definition can be [found here](https://github.com/raspberrypi/linux/blob/04c8e47067d4873c584395e5cb260b4f170a99ea/arch/arm/boot/dts/overlays/README#L1167). +The following dtoverlay definition can be [found here](https://github.com/raspberrypi/linux/blob/04c8e47067d4873c584395e5cb260b4f170a99ea/arch/arm/boot/dts/overlays/README#L1167). You can use the same behavior as for SPI0 but you can get from 1 to 3 Chip Select and you can also prevent the creation of a specific node `/dev/spidev1.0` (here on SPI1) with a specific flag `cs0_spidev=disabled` (here for Chip Select 0). So to continue the example, if we want this behavior, the dtoverlay would be for the default GPIO pin 18: @@ -127,9 +127,9 @@ Here is another example where we will use SPI4 with 2 Chip Select, CS0 to GPIO p dtoverlay=spi4-2cs,cs1_pin=17,cs1_spidev=disabled ``` -### Adding your user to the right permission group +## Adding your user to the right permission group -If you're running, or just upgraded to a version published after August 2020, this should be already done. +If you're running, or just upgraded to a version published after August 2020, this should be already done. But in case, you can always check that there are the right permissions on SPI: ```bash diff --git a/Documentation/roadmap.md b/Documentation/roadmap.md index d159fb61..291648c6 100644 --- a/Documentation/roadmap.md +++ b/Documentation/roadmap.md @@ -1,8 +1,11 @@ +# Roadmap + Our goal is to create a set of world-class APIs and tooling that will support a rich .NET IoT ecosystem. Below shows a structure of components as part of our roadmap. ## Deliverables for vNext/Future The following deliverables are not in any particular order: + * [ ] Add bindings for more devices * [ ] Add/Test support on more boards * [ ] Onboard more customers and work on making them successful @@ -41,6 +44,6 @@ The following deliverables are not in any particular order: * Stabilize Iot.Device.Bindings APIs for Device Bindings * Publish [Iot.Device.Bindings to NuGet.org](https://www.nuget.org/packages/Iot.Device.Bindings) -![](images/DotNetIotRoadmapComponents.png) +![dotnet iot rodmap](images/DotNetIotRoadmapComponents.png) More libraries and features are coming soon. Stay tuned! diff --git a/README.md b/README.md index f1df9e46..337318bc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dotnet/iot) [![Discord](https://img.shields.io/discord/755370044946513932?label=Discord)](https://discord.gg/kqWhBbj) @@ -15,7 +16,7 @@ The repository also contains [Iot.Device.Bindings](https://www.nuget.org/package ## Hardware requirements -While most of the bindings and examples in this project require and are designed to support specific hardware (such as [LCD displays](src/devices/CharacterLcd), [temperature sensors](src/devices/Dhtxx), [single-board computers](src/devices/Board/RaspberryPiBoard.cs), [microcontrollers](src/devices/Arduino), etc.), the library itself tries to be as hardware-independent as possible. Some bindings are even written to showcase the use of IOT interfaces with hardware that is already present in normal desktop computers (such as [keyboards](src/devices/Board/KeyboardGpioDriver.cs) or [CPU temperature sensors](src/devices/HardwareMonitor)). So to get started, you do not need expensive hardware. Or you can start out with cheap stuff, such as an Arduino Uno. +While most of the bindings and examples in this project require and are designed to support specific hardware (such as [LCD displays](src/devices/CharacterLcd), [temperature sensors](src/devices/Dhtxx), [single-board computers](src/devices/Board/RaspberryPiBoard.cs), [microcontrollers](src/devices/Arduino), etc.), the library itself tries to be as hardware-independent as possible. Some bindings are even written to showcase the use of IOT interfaces with hardware that is already present in normal desktop computers (such as [keyboards](src/devices/Board/KeyboardGpioDriver.cs) or [CPU temperature sensors](src/devices/HardwareMonitor)). So to get started, you do not need expensive hardware. Or you can start out with cheap stuff, such as an Arduino Uno. ## .NET Versions @@ -33,6 +34,7 @@ You can install the latest daily pre-release build of the .NET System.Device.Gpi nuget install System.Device.Gpio -PreRelease -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json nuget install Iot.Device.Bindings -PreRelease -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json ``` + ### Official Build Status [![Build Status](https://dev.azure.com/dnceng/public/_apis/build/status/dotnet/iot/dotnet.iot.github?branchName=main)](https://dev.azure.com/dnceng/public/_build/latest?definitionId=268&branchName=main) @@ -71,7 +73,7 @@ After installing, please see the following areas to learn more: All bindings (src/devices) contains a `samples` folder where you will find examples on how to use each of the devices, sensor, displays and other components. -**Important**: Please make sure you are using tag that correspond to your package version to browse and reuse the samples' code. +**Important**: Please make sure you are using tag that correspond to your package version to browse and reuse the samples' code. ![select branch](./Documentation/images/selectbranch.jpg) diff --git a/SECURITY.md b/SECURITY.md index 030ac0c0..fe3dac02 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,10 +6,10 @@ The .NET Core and ASP.NET Core support policy, including supported versions can ## Reporting a Vulnerability -Security issues and bugs should be reported privately to the Microsoft Security Response Center (MSRC), either by emailing secure@microsoft.com or via the portal at https://msrc.microsoft.com. -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your +Security issues and bugs should be reported privately to the Microsoft Security Response Center (MSRC), either by emailing secure@microsoft.com or via the portal at . +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the [MSRC Report an Issue FAQ](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue). Reports via MSRC may qualify for the .NET Core Bug Bounty. Details of the .NET Core Bug Bounty including terms and conditions are at [https://aka.ms/corebounty](https://aka.ms/corebounty). -Please do not open issues for anything you think might have a security implication. \ No newline at end of file +Please do not open issues for anything you think might have a security implication. diff --git a/eng/common/README.md b/eng/common/README.md index ff49c371..3cdf61ce 100644 --- a/eng/common/README.md +++ b/eng/common/README.md @@ -25,4 +25,4 @@ !!! Changes made in this directory are subject to being overwritten by automation !!! -The files in this directory are shared by all Arcade repos and managed by automation. If you need to make changes to these files, open an issue or submit a pull request to https://github.com/dotnet/arcade first. +The files in this directory are shared by all Arcade repos and managed by automation. If you need to make changes to these files, open an issue or submit a pull request to first. diff --git a/samples/Device Binding Template.md b/samples/Device Binding Template.md index e41b926b..5efb50a7 100644 --- a/samples/Device Binding Template.md +++ b/samples/Device Binding Template.md @@ -1,9 +1,11 @@ # [Component Name Here] ## Summary + Provide a brief description on what the component is and its functonality. ## Device Family + Provide a list of component names and link to datasheets (if available) the binding will work with. **[Family Name Here]**: [Datasheet link here] @@ -14,5 +16,6 @@ Provide any specifics related to binding API. This could include how to configu **NOTE**: Don't repeat the basics related to System.Device.API* (e.g. connection settings, etc.). This helps keep text/steps down to a minimum for maintainability. -## References +## References + Provide any references to other tutorials, blogs and hardware related to the component that could help others get started. diff --git a/samples/README.md b/samples/README.md index 084b0004..611b41af 100644 --- a/samples/README.md +++ b/samples/README.md @@ -1,6 +1,6 @@ # Using .NET for IoT Scenarios -.NET can be used to build [IoT](https://en.wikipedia.org/wiki/Internet_of_things) applications, using sensors, displays and input devices. Most ARM64 and ARM32 (hard float required) single board computers can be used, incuding [Raspberry Pi](https://www.raspberrypi.org/). +.NET can be used to build [IoT](https://en.wikipedia.org/wiki/Internet_of_things) applications, using sensors, displays and input devices. Most ARM64 and ARM32 (hard float required) single board computers can be used, incuding [Raspberry Pi](https://www.raspberrypi.org/). ## APIs @@ -8,7 +8,7 @@ The [System.Device.Gpio](https://www.nuget.org/packages/System.Device.Gpio) pack ## Samples -The following samples demonstrate various scenarios: +The following samples demonstrate various scenarios: * [Blinking LED](led-blink/README.md) * [More blinking lights](led-more-blinking-lights/README.md) diff --git a/samples/bmp280-sensor-azure-iot-hub/Readme.md b/samples/bmp280-sensor-azure-iot-hub/Readme.md index 0ad3b3a9..ae248b70 100644 --- a/samples/bmp280-sensor-azure-iot-hub/Readme.md +++ b/samples/bmp280-sensor-azure-iot-hub/Readme.md @@ -27,8 +27,8 @@ In this sample Raspberry Pi 2 will be used, you can use above Raspberry Pi 2. Th ## Prerequisite Packages -* dotnet add package Iot.Device.Bindings --source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json -* dotnet add package System.Device.Gpio --source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json +* dotnet add package Iot.Device.Bindings --source +* dotnet add package System.Device.Gpio --source * dotnet add package Microsoft.Azure.Devices.Client --version 1.38.0 ## Prepare the hardware diff --git a/samples/bmp280-sensor-azure-iot-hub/create-certificate.md b/samples/bmp280-sensor-azure-iot-hub/create-certificate.md index f22d24b4..a4b2fa71 100644 --- a/samples/bmp280-sensor-azure-iot-hub/create-certificate.md +++ b/samples/bmp280-sensor-azure-iot-hub/create-certificate.md @@ -136,7 +136,7 @@ You now have a root CA certificate. You can use it to sign device certificates. 6. Select **Generate Verification Code**. For more information, see [Prove Possession of a CA certificate](https://docs.microsoft.com/en-us/azure/iot-hub/tutorial-x509-prove-possession). -![Certificate Azure IoT Hub CA](images/certificate-iot-hub-ca.png) + ![Certificate Azure IoT Hub CA](images/certificate-iot-hub-ca.png) 7. Copy the verification code to the clipboard. You must set the verification code as the certificate subject. For example, if the verification code is BB0C656E69AF75E3FB3C8D922C1760C58C1DA5B05AAA9D0A, add that as the subject of your certificate as shown in step 9. @@ -166,7 +166,7 @@ You now have a root CA certificate. You can use it to sign device certificates. ``` -![Certificate Azure IoT Hub CA](images/certificate-iot-hub-ca-csr.png) + ![Certificate Azure IoT Hub CA](images/certificate-iot-hub-ca-csr.png) 10. Create a certificate using the root CA configuration file and the CSR for the proof of possession certificate. @@ -190,7 +190,6 @@ Navigate to your IoT Hub in the Azure portal and create a new IoT device identit ![Certificate Azure IoT Hub CA](images/create-a-device-ca-certificate.png) - ## Step 9 - Create a client device certificate To generate a client certificate, you must first generate a private key. The following command shows how to use OpenSSL to create a private key. Create the key in the subca directory. diff --git a/samples/force-sensitive-resistor/README.md b/samples/force-sensitive-resistor/README.md index d2f694e5..9103e5fe 100644 --- a/samples/force-sensitive-resistor/README.md +++ b/samples/force-sensitive-resistor/README.md @@ -4,7 +4,7 @@ Force sensitive resistors change its resistivity depending on how much it is pre FSR generates analog signal so it should be connected to analog input of a controller, as Raspberry Pi haven't analog input one can use ADC converter in between FSR and Rasp Pi. Also you can use collecting capacitor and measure its fill up time to determine if FSR is pressed. From my experience if you need more accurate measurement better to use ADC (Analog to Digital Converter). Else if only need to check/determine if FSR is pressed or not using capacitor could work. This example demonstrates both case. -## Detecting pressure/squeezing with Fsr408, Mcp3008 and Raspberry Pi +## Detecting pressure/squeezing with Fsr408, Mcp3008 and Raspberry Pi In below example MCP3008 Analog to Digital Converter used for converting FSR analog output into digital. Read value then can be used for calculating voltage, resistance and pressure force approxinmately. We need to create Mcp3008 instance depending on how you connected it to the controller, [please refer this for more about binding MCP3008](https://github.com/dotnet/iot/tree/main/src/devices/Mcp3008/samples) @@ -26,8 +26,7 @@ Code sample for [measuring pressure/squeezing with Fsr408 and ADC converter MCP3 ![Fsr408 with Mcp3008 and Raspberry Pi diagram](Fsr408_Mcp3008_RaspPi.png) -Here we supplied 3.3 volt power to FSR, if you use other power source (like 5V) please update _voltageSupplied variable with corresponding value. Also used 10 kOhm resistor, if you are using resistor with diffent resistance please update _resistance variable value for calculating voltage, FSR resistance and pressure force correctly. - +Here we supplied 3.3 volt power to FSR, if you use other power source (like 5V) please update _voltageSupplied variable with corresponding value. Also used 10 kOhm resistor, if you are using resistor with diffent resistance please update_resistance variable value for calculating voltage, FSR resistance and pressure force correctly. ## Hardware elements @@ -36,9 +35,9 @@ The following elements are used in this sample: * [Force Sensitive Resistor](https://www.adafruit.com/product/166) * [MCP3008](https://www.adafruit.com/product/856) * [Pull down Resistor 10 kOhm](https://www.adafruit.com/product/2784) +* Capacitor 0.1 micro Farade - -## Detecting touch/squeezing with Fsr408, capacitor and Raspberry Pi +## Detecting touch/squeezing with Fsr408, capacitor and Raspberry Pi Using capacitor for reading FSR analog input was producing kind of noisy signal, so from my experience if you only need to check/determine if FSR is pressed or not use of capacitor could serve well, but if you need more fine tuned measurement better use Analog to Digital Converter. @@ -67,17 +66,11 @@ You can use the following code to [detect if Force Sensitive Resistor is pressed Here we are using pin 18 for input, if you are using different pin please update _pinNumber variable. -## Hardware elements - -The following elements are used in this sample: - -* [Force Sensitive Resistor](https://www.adafruit.com/product/166) -* Capacitor 0.1 micro Farade +## References -## References The sample is based on following resources: * [FSR data sheet](https://cdn-learn.adafruit.com/assets/assets/000/010/126/original/fsrguide.pdf) -* [Reading Analog Input from a Potentiometer](https://github.com/dotnet/iot/tree/main/src/devices/Mcp3008/samples) +* [Reading Analog Input from a Potentiometer](https://github.com/dotnet/iot/tree/main/src/devices/Mcp3008/samples) * [Using an FSR](https://learn.adafruit.com/force-sensitive-resistor-fsr/using-an-fsr) * [Basic Resistor Sensor Reading on Raspberry Pi](https://learn.adafruit.com/basic-resistor-sensor-reading-on-raspberry-pi) diff --git a/samples/led-blink-multiple/README.md b/samples/led-blink-multiple/README.md index fd8023d1..de6ac73e 100644 --- a/samples/led-blink-multiple/README.md +++ b/samples/led-blink-multiple/README.md @@ -51,4 +51,4 @@ The following [fritzing diagram](rpi-led-multiple.fzz) demonstrates how you shou * [Diffused LEDs](https://www.adafruit.com/product/4203) * [All about LEDs](https://learn.adafruit.com/all-about-leds) * [Blinking an LED with Arduino](https://learn.adafruit.com/adafruit-arduino-lesson-2-leds/blinking-the-led) -* [Blinking an LED with Python](https://learn.adafruit.com/blinking-an-led-with-beaglebone-black/writing-a-program) \ No newline at end of file +* [Blinking an LED with Python](https://learn.adafruit.com/blinking-an-led-with-beaglebone-black/writing-a-program) diff --git a/samples/led-blink/README.md b/samples/led-blink/README.md index fa562030..282f3226 100644 --- a/samples/led-blink/README.md +++ b/samples/led-blink/README.md @@ -42,7 +42,7 @@ $ docker run --rm --device /dev/gpiomem led-blink Alternatively, you can run the container by mounting sysfs as a privileged container, but that's less secure and is a slower way to interact with GPIO pins. ```console -$ docker run --rm -v /sys:/sys --privileged led-blink +docker run --rm -v /sys:/sys --privileged led-blink ``` ## Resources @@ -50,5 +50,5 @@ $ docker run --rm -v /sys:/sys --privileged led-blink * [.NET IoT Docs](https://docs.microsoft.com/dotnet/iot/) * [Diffused LEDs](https://www.adafruit.com/product/4203) * [All about LEDs](https://learn.adafruit.com/all-about-leds) -- [Blinking an LED with Arduino](https://learn.adafruit.com/adafruit-arduino-lesson-2-leds/blinking-the-led) -- [Blinking an LED with Python](https://learn.adafruit.com/blinking-an-led-with-beaglebone-black/writing-a-program) \ No newline at end of file +* [Blinking an LED with Arduino](https://learn.adafruit.com/adafruit-arduino-lesson-2-leds/blinking-the-led) +* [Blinking an LED with Python](https://learn.adafruit.com/blinking-an-led-with-beaglebone-black/writing-a-program) diff --git a/samples/led-more-blinking-lights/README.md b/samples/led-more-blinking-lights/README.md index 1b491090..5769bcc4 100644 --- a/samples/led-more-blinking-lights/README.md +++ b/samples/led-more-blinking-lights/README.md @@ -7,7 +7,7 @@ This [sample](Program.cs) demonstrates blinking multiple LED on different schedu This sample demonstrates how to use five different elements together, three LEDs, a potentiometer and a button. There is no one specific code element to call out here. Each element is controlled in a different way. You will find that different algorithms were needed to control LED timing than in the [Blink an LED](../led-blink/README.md) example. In particular, this sample implements the following: * Different lighting schedules for different LEDs using the [TimeEnvelope](TimeEnvelope.cs) type. -* Integrating a factor in the lighting schedule based on the value returned from the potentiometer, implemented in the [Volume ](Volume.cs) type. +* Integrating a factor in the lighting schedule based on the value returned from the potentiometer, implemented in the [Volume](Volume.cs) type. ## Breadboard layout @@ -27,4 +27,4 @@ The following elements are used in this sample: ## Resources * [Using .NET Core for IoT Scenarios](../README.md) -* [All about LEDs](https://learn.adafruit.com/all-about-leds) \ No newline at end of file +* [All about LEDs](https://learn.adafruit.com/all-about-leds) diff --git a/samples/serialport-arduino/README.md b/samples/serialport-arduino/README.md index 36f00027..d611e867 100644 --- a/samples/serialport-arduino/README.md +++ b/samples/serialport-arduino/README.md @@ -1,14 +1,15 @@ # Controlling Arduino with .NET using Raspberry Pi -https://www.youtube.com/watch?v=TW4K64hfa5U +[Watch the video](https://www.youtube.com/watch?v=TW4K64hfa5U) for this setup: - +![setup](setup-close.jpg) ## Overview This sample shows how to control Arduino with .NET using serial port. Sample consists of two parts: + - Arduino Playground Express app lighting 2 RGB LEDs in a circle (there are 10 LEDS in a shape of circle, consecutive LEDs are being lighted making effect of spinning - see diagram below for reference) - project has couple of parameters which can be controlled: rate of spinning, LED color, direction and also pausing the spinning - .NET app using System.IO.Ports to communicate with Arduino - in this example we will use Raspberry Pi 3 model B. @@ -23,7 +24,7 @@ Note: If you're planning to connect UART with i.e. RS232 you will need converter [Fritzing Diagram](arduino-pi-sp.fzz) - `Arduino Playground Express` part is missing by default in Fritzing - it can be downloaded [here](https://github.com/adafruit/Fritzing-Library/blob/master/parts/Adafruit%20Circuit%20Playground%20Express.fzpz) - +![arduino setup](arduino-pi-sp_bb.png) ## Communication protocol @@ -44,7 +45,7 @@ Essential piece which transmit the data is just `sp.WriteLine("")` To setup such app from the scratch (assumes your folder name is `arduino-demo` and that UART on Raspberry Pi is `/dev/ttyS0`): -``` +```shell dotnet new console dotnet add package System.IO.Ports -v 4.6.0-preview.18571.3 ``` @@ -57,14 +58,14 @@ add runtime identifier in the property group to make it easier to publish (you c edit the app and then to publish it (note: in many cases it might be easier to publish app elsewhere than Raspbery Pi and then copy it over to Raspberry Pi through i.e. SSH - if copying from Windows you might need to also add executable permission to your executable) -``` +```shell dotnet publish ``` publish command will produce binaries in `bin/Debug/netcoreapp3.1/linux-arm/publish` To run your app simply call it while in that directory -``` +```shell ./arduino-demo /dev/ttyS0 ``` @@ -78,4 +79,4 @@ The example was built using [Arduino IDE](https://www.arduino.cc/en/Main/Softwar [See Arduino sketch file](uart-demo.ino) - +![setup](setup-full.jpg) diff --git a/src/devices/Bmm150/README.md b/src/devices/Bmm150/README.md index 72bd4ae9..d34d1672 100644 --- a/src/devices/Bmm150/README.md +++ b/src/devices/Bmm150/README.md @@ -1,6 +1,6 @@ # Bmm150 - Magnetometer -The Bmm150 is a magnetometer that can be controlled either thru I2C either thru SPI. +The Bmm150 is a magnetometer that can be controlled either thru I2C either thru SPI. This implementation was tested in a ESP32 platform, specificaly in a [M5Stack Gray](https://shop.m5stack.com/products/grey-development-core). ## Documentation @@ -74,7 +74,7 @@ Running the calibration properly require to **move the sensor in all the possibl ![raw data](./corrcalib.png) -To create those cloud point graphs, every cloud is a coordinate of X-Y, Y-Z and Z-X. +To create those cloud point graphs, every cloud is a coordinate of X-Y, Y-Z and Z-X. Once the calibration is done, you will be able to read the data with the bias corrected using the ```ReadMagnetometer``` function. You will still be able to read the data without any calibration using the ```ReadMagnetometerWithoutCalibration``` function. diff --git a/src/devices/DCMotor/README.md b/src/devices/DCMotor/README.md index 6d8ca106..3ac83303 100644 --- a/src/devices/DCMotor/README.md +++ b/src/devices/DCMotor/README.md @@ -7,7 +7,7 @@ DC motors are controlled by simply providing voltage on the inputs (inverted vol DC motors can be controlled with 1, 2 or 3 pins. Please refer to the [sample](./samples/Program.cs) to see how to connect it. -**Never connect DC motor directly to your board, instead use i.e. H-bridge** +> **Important**: Never connect DC motor directly to your board, instead use i.e. H-bridge ## 3- vs 1/2-pin mode diff --git a/src/devices/Device-Index.md b/src/devices/Device-Index.md index 332ad525..b20def8b 100755 --- a/src/devices/Device-Index.md +++ b/src/devices/Device-Index.md @@ -1,3 +1,5 @@ + + # Alphabetical Device Index diff --git a/src/devices/Dhtxx/README.md b/src/devices/Dhtxx/README.md index 3c7d7dfb..fb9a078e 100644 --- a/src/devices/Dhtxx/README.md +++ b/src/devices/Dhtxx/README.md @@ -94,21 +94,21 @@ The DHT sensors are very sensitive, avoid too long cables, electromagnetic pertu ## FAQ -**I always get wrong measurements, what's happening?** +### I always get wrong measurements, what's happening? Please check that the sensor is plugged correctly, make sure you are using the correct pin. Please check you are using the correct sensor, only DHT10 and DHT12 supports I2C. All others support only GPIO with 1 wire protocol. DHT12 supports both. -**The data I measure are not correct, humidity seems ok but temperature is always weird, what's the problem?** +### The data I measure are not correct, humidity seems ok but temperature is always weird, what's the problem? Please check you are using the correct sensor. Refer to the top part of this page to check which sensor you have. Using a DHT11 instead of a DHT22 will give you a wrong temperature. -**I am trying to get a temperature and humidity 5 times per seconds but I mainly get wrong measurements, why?** +### I am trying to get a temperature and humidity 5 times per seconds but I mainly get wrong measurements, why? This is absolutely normal, you should check the measurements once every 2 seconds approximately. Don't try to get more measures than once every 2 seconds. -**When reading the temperature and humidity and trying to write the data in the console, I get an exception, why?** +### When reading the temperature and humidity and trying to write the data in the console, I get an exception, why? You need to check first if the measurement has been successful. If the measurement hasn't been successful, the default values will be NaN and so you won't be able to convert the temperature or humidity and you'll get an exception. This is the correct way of first reading the sensor and then checking the reading was correct and finally using the temperature and humidity data: @@ -122,7 +122,7 @@ if (dht.IsLastReadSuccessful) } ``` -**I have a Raspberry Pi 4 and I get an exception when creating the DHT sensor** +### I have a Raspberry Pi 4 and I get an exception when creating the DHT sensor See this [issue 1145](https://github.com/dotnet/iot/issues/1145). We're actively trying to fix it automatically. You will have to force using either the Raspberry Pi 3 driver, either the LibGpiodDriver. This is how you can force using a specific drive, in this case the Raspberry Pi 3 one which will work: @@ -133,7 +133,7 @@ var controller = new GpioController(PinNumberingScheme.Logical, driver); var dht = new Dht11(4, gpioController: controller); ``` -**My DHT sensor using 1 wire protocol is not working on my Raspberry Pi with Windows 10 IoT Core, what can I do?** +### My DHT sensor using 1 wire protocol is not working on my Raspberry Pi with Windows 10 IoT Core, what can I do? On the RPi with any of the DHT sensor, 1-Wire works using Raspian but not with Windows 10 IoT Core. The device has to switch the 1-wire pin between input and output and vice versa. It seems that Windows IoT Core OS can't switch the pin direction quick enough. There have been suggestions for using two pins; one for input and one for output. This solution has not been implemented here, but these are some handy links that may help setting that up:_ diff --git a/src/devices/Gpio/README.md b/src/devices/Gpio/README.md index 11c6f4df..38656e23 100644 --- a/src/devices/Gpio/README.md +++ b/src/devices/Gpio/README.md @@ -19,7 +19,7 @@ Benchmarking with **Orange Pi Zero**, select GPIO 6 (Logical). The operating sys | :-: | :-: | :-: | :-: | :-: | :-: | | SunxiDriver | C# | - | 2020-02-20 | 185 KHz | ![sunxi](./imgs/SunxiDriver/sunxi.jpg) | | SysFsDriver | C# | System.Device.Gpio 1.3.0 | 2020-02-20 | 692 Hz | ![sysfs](./imgs/SunxiDriver/sysfs.jpg) | -| LibGpiodDriver | C# | System.Device.Gpio 1.3.0
libgpiod 1.2-3 | 2020-02-20 | 81 KHz | ![libgpiod](./imgs/SunxiDriver/libgpiod.jpg) | +| LibGpiodDriver | C# | System.Device.Gpio 1.3.0 - libgpiod 1.2-3 | 2020-02-20 | 81 KHz | ![libgpiod](./imgs/SunxiDriver/libgpiod.jpg) | | [wiringOP](https://github.com/orangepi-xunlong/wiringOP) | C | 35de015 | 2020-02-22 | 1.10 MHz | ![wiringOP](./imgs/SunxiDriver/wiringOP.jpg) | ### RockchipDriver @@ -30,7 +30,7 @@ Benchmarking with **Orange Pi 4**, select GPIO 150 (Logical). The operating syst | :-: | :-: | :-: | :-: | :-: | :-: | | RockchipDriver | C# | - | 2020-02-22 | 516 KHz | ![rockchip](./imgs/RockchipDriver/rockchip.jpg) | | SysFsDriver | C# | System.Device.Gpio 1.3.0 | 2020-02-22 | 4.27 KHz | ![sysfs](./imgs/RockchipDriver/sysfs.jpg) | -| LibGpiodDriver | C# | System.Device.Gpio 1.3.0
libgpiod 1.2-3 | 2020-02-22 | 174 KHz | ![libgpiod](./imgs/RockchipDriver/libgpiod.jpg) | +| LibGpiodDriver | C# | System.Device.Gpio 1.3.0 - libgpiod 1.2-3 | 2020-02-22 | 174 KHz | ![libgpiod](./imgs/RockchipDriver/libgpiod.jpg) | | [wiringOP](https://github.com/orangepi-xunlong/wiringOP) | C | 35de015 | 2020-02-22 | 584 KHz | ![wiringgOP](./imgs/RockchipDriver/wiringOP.jpg) | ## Usage diff --git a/src/devices/Ip5306/README.md b/src/devices/Ip5306/README.md index 8b043592..a73e3ec0 100644 --- a/src/devices/Ip5306/README.md +++ b/src/devices/Ip5306/README.md @@ -95,4 +95,3 @@ power.LightDutyShutdownTime = LightDutyShutdownTime.S32; power.ChargingCutOffCurrent = ChargingCutOffCurrent.C500mA; power.ChargingCuttOffVoltage = ChargingCutOffVoltage.V4_2; ``` - \ No newline at end of file diff --git a/src/devices/Mcp960x/README.md b/src/devices/Mcp960x/README.md index 3950ca7c..fa561118 100644 --- a/src/devices/Mcp960x/README.md +++ b/src/devices/Mcp960x/README.md @@ -1,15 +1,16 @@ -# MCP960X - device family of cold-junction compensated thermocouple to digital converter +# MCP960X - device family of cold-junction compensated thermocouple to digital converter The MCP960X device family is an I2C interface cold-junction compensated thermocouple to digital converter. Supported thermocouple types (designated by NIST ITS-90) are: K, J, T, N, S, E, B and R. -The MCP9600/01 converts the thermocouple EMF to degree Celsius with integrated cold-junction compensation. +The MCP9600/01 converts the thermocouple EMF to degree Celsius with integrated cold-junction compensation. **Note:** _Default thermocouple type is K_ ## Sensor Image + ![Illustration of wiring from a Raspberry Pi device](device.png) -## Documentation +## Documentation **MCP960X** [datasheet](https://www.microchip.com/en-us/product/MCP9600) diff --git a/src/devices/Pcx857x/README.md b/src/devices/Pcx857x/README.md index 09d493ca..f99002fb 100644 --- a/src/devices/Pcx857x/README.md +++ b/src/devices/Pcx857x/README.md @@ -11,7 +11,7 @@ PCX857X devices contain different markings to distinguish features like packagin * PCA8574 [datasheet](https://www.nxp.com/docs/en/data-sheet/PCA8574_PCA8574A.pdf) * PCA8575 [datasheet](https://www.nxp.com/docs/en/data-sheet/PCA8575.pdf) -#### Usage +## Usage ```csharp // 0x20 is the device address in this example. diff --git a/src/devices/README.md b/src/devices/README.md index b3d540e7..4562fe5c 100755 --- a/src/devices/README.md +++ b/src/devices/README.md @@ -1,3 +1,5 @@ + + # Device Bindings This directory is intended for device bindings, sensors, displays, human interface devices and anything else that requires software to control. We want to establish a rich set of quality .NET bindings to make it straightforward to use .NET to connect devices together to produce weird and wonderful IoT applications. diff --git a/src/devices/Scd4x/README.md b/src/devices/Scd4x/README.md index 745bce85..0b4983a7 100644 --- a/src/devices/Scd4x/README.md +++ b/src/devices/Scd4x/README.md @@ -1,3 +1,4 @@ + # SCD4x - CO2, Temperature & Humidity Sensor SCD4x is a CO2, temperature & humidity sensor from Sensirion. This project supports the SCD40 and SCD41 sensors. @@ -107,4 +108,4 @@ while (true) // read humidity (%) double humidity = hum.Value.Percent; } -``` \ No newline at end of file +``` diff --git a/src/devices/Sht4x/README.md b/src/devices/Sht4x/README.md index 8f77a392..0f8a2bce 100644 --- a/src/devices/Sht4x/README.md +++ b/src/devices/Sht4x/README.md @@ -49,4 +49,4 @@ if(rh is null || t is null) double humidity = rh.Value.Percent; // read temperature (℃) double temperature = t.Value.Celsius; -``` \ No newline at end of file +``` diff --git a/src/devices/UFireIse/README.md b/src/devices/UFireIse/README.md index 70ef0fc1..71b2d3ca 100644 --- a/src/devices/UFireIse/README.md +++ b/src/devices/UFireIse/README.md @@ -29,14 +29,14 @@ To read the ORP (OxidationReductionPotential) value use this example ```csharp using (UFireOrp uFireOrp = new UFireOrp(device)) { - if (uFireOrp.TryMeasureOxidationReductionPotential(out ElectricPotential orp)) - { - Console.WriteLine("Eh:" + orp.Millivolts); - } - else - { - Console.WriteLine("Not possible to measure pH"); - } + if (uFireOrp.TryMeasureOxidationReductionPotential(out ElectricPotential orp)) + { + Console.WriteLine("Eh:" + orp.Millivolts); + } + else + { + Console.WriteLine("Not possible to measure pH"); + } } ``` @@ -61,15 +61,15 @@ To read the Ph (Power of Hydrogen) value use this example ```csharp using (UFirePh uFire_pH = new UFirePh(device)) { - Console.WriteLine("mV:" + uFire_pH.Measure().Millivolts); - - if (uFire_pH.TryMeasurepH(out float pH)) - { - Console.WriteLine("pH:" + pH); - } - else - { - Console.WriteLine("Not possible to measure pH"); - } + Console.WriteLine("mV:" + uFire_pH.Measure().Millivolts); + + if (uFire_pH.TryMeasurepH(out float pH)) + { + Console.WriteLine("pH:" + pH); + } + else + { + Console.WriteLine("Not possible to measure pH"); + } } ``` diff --git a/tools/DevicesApiTester/README.md b/tools/DevicesApiTester/README.md index 984f1592..10d4801f 100644 --- a/tools/DevicesApiTester/README.md +++ b/tools/DevicesApiTester/README.md @@ -20,20 +20,25 @@ Each of the commands has an `ExecuteAsync` or `Execute` method at the top of the ## Examples -1. See a list of all commands:
-`DeviceApiTester help` +1. See a list of all commands: -2. Show the `gpio-button-event` command's syntax:
-`DeviceApiTester help gpio-button-event` + `DeviceApiTester help` -3. Run the command with required parameters:
-`DeviceApiTester gpio-button-event --button-pin 5 --led-pin 6` +2. Show the `gpio-button-event` command's syntax: -4. Run the command with many optional parameters:
-`DeviceApiTester gpio-button-event --scheme Board --button-pin 29 --pressed-value Falling --led-pin 31 --on-value Low --driver RPi3` + `DeviceApiTester help gpio-button-event` -5. Run the command with many optional parameters using single-characters options:
-`DeviceApiTester gpio-button-event -s Board -b 29 -p Falling -l 31 --on-value Low -d RPi3` +3. Run the command with required parameters: + + `DeviceApiTester gpio-button-event --button-pin 5 --led-pin 6` + +4. Run the command with many optional parameters: + + `DeviceApiTester gpio-button-event --scheme Board --button-pin 29 --pressed-value Falling --led-pin 31 --on-value Low --driver RPi3` + +5. Run the command with many optional parameters using single-characters options: + + `DeviceApiTester gpio-button-event -s Board -b 29 -p Falling -l 31 --on-value Low -d RPi3` ## Adding Additional Commands @@ -47,18 +52,22 @@ Each of the commands has an `ExecuteAsync` or `Execute` method at the top of the } } ``` - + - It's easiest to begin by copying one of the existing commands. - - Keep the new command class within the folder for connection type:
+ - Keep the new command class within the folder for connection type: + `Commands/Gpio`, `Commands/I2c`, `Commands/Spi`. 2. Add or modify the `Verb` attribute to describe the command: + ```csharp [Verb("i2c-my-command", HelpText = "This command does something with an I2C connection.")] ``` + - Prefix the command's verb with its connection type: `gpio-`, `i2c-`, `spi-` 3. Implement either the `ICommandVerb` or `ICommandVerbAsync` interface on your command class: + ```csharp public class MyCommand : I2cCommand, ICommandVerb { @@ -69,7 +78,9 @@ Each of the commands has an `ExecuteAsync` or `Execute` method at the top of the } } ``` + or + ```csharp public class MyCommand : I2cCommand, ICommandVerbAsync { @@ -83,12 +94,14 @@ Each of the commands has an `ExecuteAsync` or `Execute` method at the top of the ``` 4. Add automatic properties for command options: + ```csharp [Option('c', "cool-option", HelpText = "A cool option argument", Required = false, Default = 0)] public int CoolOption { get; set; } ``` 5. Use the properties in your execution: + ```csharp public int Execute() { @@ -98,7 +111,8 @@ Each of the commands has an `ExecuteAsync` or `Execute` method at the top of the ``` 6. Deploy and run: - ``` + + ```shell DeviceApiTester help DeviceApiTester help i2c-my-command DeviceApiTester i2c-my-command --cool-option 42 diff --git a/tools/GenerateDocFxStructure/README.md b/tools/GenerateDocFxStructure/README.md index ec7e8259..cdd162ff 100644 --- a/tools/GenerateDocFxStructure/README.md +++ b/tools/GenerateDocFxStructure/README.md @@ -2,7 +2,7 @@ In order to reuse the README for each binding and reference them from the source comments (triple slash), the files need to be moved into a specific directory. -This directory cannot include the images and other medias, they need to be moved in another folder. +This directory cannot include the images and other medias, they need to be moved in another folder. The links to those media files need to be adjusted as well. diff --git a/tools/device-listing/README.md b/tools/device-listing/README.md index 6871427b..61165640 100644 --- a/tools/device-listing/README.md +++ b/tools/device-listing/README.md @@ -1,4 +1,3 @@ # Device listing generator Run `dotnet run` on this project to auto-generate description in `src/devices/README.md`. - diff --git a/tools/templates/DeviceBindingTemplate/README.md b/tools/templates/DeviceBindingTemplate/README.md index 7e262668..89e55c39 100644 --- a/tools/templates/DeviceBindingTemplate/README.md +++ b/tools/templates/DeviceBindingTemplate/README.md @@ -3,6 +3,7 @@ The Device Binding Template provides an easy way to create device binding projects. This template is based on the [.NET Templates](https://github.com/dotnet/templating). ## How to Install + Currently, there is no NuGet package available so the template folder must be stored locally. Use the following command to install the template where `PATH` is the directory path the template was stored. ```console @@ -10,6 +11,7 @@ dotnet new -i C:\[PATH]\iot\tools\templates\DeviceBindingTemplate\dotnet_new_dev ``` ## How to Uninstall + The template can be uninstalled by using the following command where `PATH` is the directory path the template was stored. ```console @@ -17,17 +19,19 @@ dotnet new -u C:\[PATH]\iot\tools\templates\DeviceBindingTemplate\dotnet_new_dev ``` ## Example Device Binding + Use the following command to create a device binding project. - * `PATH` is the recommended directory path where other device bindings are located in the repo structure. - * The output parameter (-o) is not required when working in the current directory expected to create the binding project. +* `PATH` is the recommended directory path where other device bindings are located in the repo structure. +* The output parameter (-o) is not required when working in the current directory expected to create the binding project. ```console dotnet new device-binding -n Foo -o C:\[PATH]\iot\src\devices\Foo ``` + The following device binding structure will be created after running the command. -``` +```text iot/ src/ devices/ @@ -45,4 +49,5 @@ iot/ ``` ## Tests Project + There is an optional test project created when the device binding project is created. The tests folder can be deleted if not used. diff --git a/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/README.md b/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/README.md index 8c499f0e..ba2a4299 100644 --- a/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/README.md +++ b/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/README.md @@ -1,9 +1,11 @@ # _DeviceBinding ## Summary + Provide a brief description on what the component is and its functionality. ## Device Family + Provide a list of component names and link to datasheets (if available) the binding will work with. **[Family Name Here]**: [Datasheet link here] @@ -14,5 +16,6 @@ Provide any specifics related to binding API. This could include how to configu **NOTE**: Don't repeat the basics related to System.Device.API* (e.g. connection settings, etc.). This helps keep text/steps down to a minimum for maintainability. -## References +## References + Provide any references to other tutorials, blogs and hardware related to the component that could help others get started. diff --git a/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/samples/README.md b/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/samples/README.md index f295773e..c7e16de8 100644 --- a/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/samples/README.md +++ b/tools/templates/DeviceBindingTemplate/dotnet_new_device-binding_csharp/samples/README.md @@ -1,4 +1,3 @@ # TODO: This needs to be determined Help Wanted Please - -- GitLab