├── .editorconfig
├── .gitignore
├── .travis.yml
├── .vscode
└── settings.json
├── CHANGELOG.md
├── Examples
├── Microsoft.PowerShell.IoT.ADXL345
│ ├── Microsoft.PowerShell.IoT.ADXL345.psd1
│ ├── Microsoft.PowerShell.IoT.ADXL345.psm1
│ └── README.md
├── Microsoft.PowerShell.IoT.BME280
│ ├── Microsoft.PowerShell.IoT.BME280.psd1
│ ├── Microsoft.PowerShell.IoT.BME280.psm1
│ └── README.md
├── Microsoft.PowerShell.IoT.Fan
│ ├── Microsoft.PowerShell.IoT.Fan.psd1
│ ├── Microsoft.PowerShell.IoT.Fan.psm1
│ ├── README.md
│ └── SmartFan.ps1
├── Microsoft.PowerShell.IoT.LED
│ ├── Microsoft.PowerShell.IoT.LED.psd1
│ ├── Microsoft.PowerShell.IoT.LED.psm1
│ └── README.md
├── Microsoft.PowerShell.IoT.Plant
│ ├── Microsoft.PowerShell.IoT.Plant.psd1
│ ├── Microsoft.PowerShell.IoT.Plant.psm1
│ ├── README.md
│ └── full-plant-demo.ps1
├── Microsoft.PowerShell.IoT.SSD1306
│ ├── Microsoft.PowerShell.IoT.SSD1306.psd1
│ ├── Microsoft.PowerShell.IoT.SSD1306.psm1
│ └── README.md
├── Microsoft.PowerShell.IoT.Scroll_pHat
│ ├── Microsoft.PowerShell.IoT.SadJoey.ps1
│ └── README.md
└── README.md
├── LICENSE.txt
├── Move-PSIoTBuild.ps1
├── NuGet.config
├── README.md
├── SimpleBuild.ps1
├── appveyor.yml
├── azure-pipelines-release.yml
├── build.ps1
├── docs
├── README.md
├── help
│ ├── Get-GpioPin.md
│ ├── Get-I2CDevice.md
│ ├── Get-I2CRegister.md
│ ├── Microsoft.PowerShell.IoT.md
│ ├── Send-SPIData.md
│ ├── Set-GpioPin.md
│ └── Set-I2CRegister.md
├── remoting.md
└── rpi3_pin_layout.md
├── psiot.build.ps1
├── src
├── Microsoft.PowerShell.IoT.sln
├── Microsoft.PowerShell.IoT
│ ├── Gpio
│ │ ├── Get
│ │ │ └── GetGpioPin.cs
│ │ ├── GpioCmdletBase.cs
│ │ ├── GpioPinData.cs
│ │ └── Set
│ │ │ └── SetGpioPin.cs
│ ├── I2c
│ │ ├── Get
│ │ │ ├── GetI2cDevice.cs
│ │ │ └── GetI2cRegister.cs
│ │ ├── I2cDevice.cs
│ │ ├── I2cRegisterData.cs
│ │ └── Set
│ │ │ └── SetI2cRegister.cs
│ ├── Microsoft.PowerShell.IoT.csproj
│ ├── Microsoft.PowerShell.IoT.psd1
│ ├── SPI
│ │ ├── SPIData.cs
│ │ └── Send
│ │ │ └── SendSPIData.cs
│ ├── gen
│ │ └── Resources.cs
│ └── resources
│ │ └── Resources.resx
└── ResGen
│ ├── Program.cs
│ ├── README.md
│ └── ResGen.csproj
├── test
└── psiot.Tests.ps1
├── tools
├── vsts.ps1
└── vstsBuild.psm1
└── vsts.yml
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | insert_final_newline = true
6 |
7 | [*.{cs,ps1,psd1,psm1}]
8 | file_header_template = Copyright (c) Microsoft Corporation.\nLicensed under the MIT License.
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/visualstudio
3 |
4 | ### VisualStudio ###
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 | ##
8 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.userosscache
14 | *.sln.docstates
15 |
16 | # User-specific files (MonoDevelop/Xamarin Studio)
17 | *.userprefs
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | bld/
27 | [Bb]in/
28 | [Oo]bj/
29 | [Ll]og/
30 |
31 | # Visual Studio 2015 cache/options directory
32 | .vs/
33 | # Uncomment if you have tasks that create the project's static files in wwwroot
34 | #wwwroot/
35 |
36 | # MSTest test Results
37 | [Tt]est[Rr]esult*/
38 | [Bb]uild[Ll]og.*
39 |
40 | # NUNIT
41 | *.VisualState.xml
42 | TestResult.xml
43 | TestsResults.xml
44 |
45 | # Build Results of an ATL Project
46 | [Dd]ebugPS/
47 | [Rr]eleasePS/
48 | dlldata.c
49 |
50 | # .NET Core
51 | project.lock.json
52 | project.fragment.lock.json
53 | artifacts/
54 | **/Properties/launchSettings.json
55 |
56 | *_i.c
57 | *_p.c
58 | *_i.h
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.svclog
79 | *.scc
80 |
81 | # Chutzpah Test files
82 | _Chutzpah*
83 |
84 | # Visual C++ cache files
85 | ipch/
86 | *.aps
87 | *.ncb
88 | *.opendb
89 | *.opensdf
90 | *.sdf
91 | *.cachefile
92 | *.VC.db
93 | *.VC.VC.opendb
94 |
95 | # Visual Studio profiler
96 | *.psess
97 | *.vsp
98 | *.vspx
99 | *.sap
100 |
101 | # TFS 2012 Local Workspace
102 | $tf/
103 |
104 | # Guidance Automation Toolkit
105 | *.gpState
106 |
107 | # ReSharper is a .NET coding add-in
108 | _ReSharper*/
109 | *.[Rr]e[Ss]harper
110 | *.DotSettings.user
111 |
112 | # JustCode is a .NET coding add-in
113 | .JustCode
114 |
115 | # TeamCity is a build add-in
116 | _TeamCity*
117 |
118 | # DotCover is a Code Coverage Tool
119 | *.dotCover
120 |
121 | # Visual Studio code coverage results
122 | *.coverage
123 | *.coveragexml
124 |
125 | # NCrunch
126 | _NCrunch_*
127 | .*crunch*.local.xml
128 | nCrunchTemp_*
129 |
130 | # MightyMoose
131 | *.mm.*
132 | AutoTest.Net/
133 |
134 | # Web workbench (sass)
135 | .sass-cache/
136 |
137 | # Installshield output folder
138 | [Ee]xpress/
139 |
140 | # DocProject is a documentation generator add-in
141 | DocProject/buildhelp/
142 | DocProject/Help/*.HxT
143 | DocProject/Help/*.HxC
144 | DocProject/Help/*.hhc
145 | DocProject/Help/*.hhk
146 | DocProject/Help/*.hhp
147 | DocProject/Help/Html2
148 | DocProject/Help/html
149 |
150 | # Click-Once directory
151 | publish/
152 |
153 | # Publish Web Output
154 | *.[Pp]ublish.xml
155 | *.azurePubxml
156 | # TODO: Uncomment the next line to ignore your web deploy settings.
157 | # By default, sensitive information, such as encrypted password
158 | # should be stored in the .pubxml.user file.
159 | #*.pubxml
160 | *.pubxml.user
161 | *.publishproj
162 |
163 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
164 | # checkin your Azure Web App publish settings, but sensitive information contained
165 | # in these scripts will be unencrypted
166 | PublishScripts/
167 |
168 | # NuGet Packages
169 | *.nupkg
170 | # The packages folder can be ignored because of Package Restore
171 | **/packages/*
172 | # except build/, which is used as an MSBuild target.
173 | !**/packages/build/
174 | # Uncomment if necessary however generally it will be regenerated when needed
175 | #!**/packages/repositories.config
176 | # NuGet v3's project.json files produces more ignorable files
177 | *.nuget.props
178 | *.nuget.targets
179 |
180 | # Microsoft Azure Build Output
181 | csx/
182 | *.build.csdef
183 |
184 | # Microsoft Azure Emulator
185 | ecf/
186 | rcf/
187 |
188 | # Windows Store app package directories and files
189 | AppPackages/
190 | BundleArtifacts/
191 | Package.StoreAssociation.xml
192 | _pkginfo.txt
193 |
194 | # Visual Studio cache files
195 | # files ending in .cache can be ignored
196 | *.[Cc]ache
197 | # but keep track of directories ending in .cache
198 | !*.[Cc]ache/
199 |
200 | # Others
201 | ClientBin/
202 | ~$*
203 | *~
204 | *.dbmdl
205 | *.dbproj.schemaview
206 | *.jfm
207 | *.pfx
208 | *.publishsettings
209 | orleans.codegen.cs
210 |
211 | # Since there are multiple workflows, uncomment next line to ignore bower_components
212 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
213 | #bower_components/
214 |
215 | # RIA/Silverlight projects
216 | Generated_Code/
217 |
218 | # Backup & report files from converting an old project file
219 | # to a newer Visual Studio version. Backup files are not needed,
220 | # because we have git ;-)
221 | _UpgradeReport_Files/
222 | Backup*/
223 | UpgradeLog*.XML
224 | UpgradeLog*.htm
225 |
226 | # SQL Server files
227 | *.mdf
228 | *.ldf
229 | *.ndf
230 |
231 | # Business Intelligence projects
232 | *.rdl.data
233 | *.bim.layout
234 | *.bim_*.settings
235 |
236 | # Microsoft Fakes
237 | FakesAssemblies/
238 |
239 | # GhostDoc plugin setting file
240 | *.GhostDoc.xml
241 |
242 | # Node.js Tools for Visual Studio
243 | .ntvs_analysis.dat
244 | node_modules/
245 |
246 | # Typescript v1 declaration files
247 | typings/
248 |
249 | # Visual Studio 6 build log
250 | *.plg
251 |
252 | # Visual Studio 6 workspace options file
253 | *.opt
254 |
255 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
256 | *.vbw
257 |
258 | # Visual Studio LightSwitch build output
259 | **/*.HTMLClient/GeneratedArtifacts
260 | **/*.DesktopClient/GeneratedArtifacts
261 | **/*.DesktopClient/ModelManifest.xml
262 | **/*.Server/GeneratedArtifacts
263 | **/*.Server/ModelManifest.xml
264 | _Pvt_Extensions
265 |
266 | # Paket dependency manager
267 | .paket/paket.exe
268 | paket-files/
269 |
270 | # FAKE - F# Make
271 | .fake/
272 |
273 | # JetBrains Rider
274 | .idea/
275 | *.sln.iml
276 |
277 | # CodeRush
278 | .cr/
279 |
280 | # Python Tools for Visual Studio (PTVS)
281 | __pycache__/
282 | *.pyc
283 |
284 | # Cake - Uncomment if you are using it
285 | # tools/**
286 | # !tools/packages.config
287 |
288 | # Telerik's JustMock configuration file
289 | *.jmconfig
290 |
291 | # BizTalk build output
292 | *.btp.cs
293 | *.btm.cs
294 | *.odx.cs
295 | *.xsd.cs
296 |
297 | ### VisualStudio Patch ###
298 | # By default, sensitive information, such as encrypted password
299 | # should be stored in the .pubxml.user file.
300 |
301 |
302 | # End of https://www.gitignore.io/api/visualstudio
303 |
304 | out
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 |
3 | matrix:
4 | include:
5 | - os: osx
6 | dotnet: 2.1.4
7 | mono: none
8 | osx_image: xcode9.1
9 | before_install:
10 | - brew update
11 | - brew tap caskroom/cask
12 | - brew cask install powershell
13 | - os: linux
14 | dotnet: 2.1.4
15 | mono: none
16 | dist: trusty
17 | sudo: required
18 | addons:
19 | apt:
20 | sources:
21 | - sourceline: deb [arch=amd64] https://packages.microsoft.com/ubuntu/14.04/prod trusty main
22 | key_url: https://packages.microsoft.com/keys/microsoft.asc
23 | packages:
24 | - powershell
25 |
26 | script:
27 | - pwsh -c 'Install-Module InvokeBuild -Force -Scope CurrentUser; Invoke-Build'
28 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.detectIndentation": false,
3 | "editor.tabSize": 4,
4 | "editor.insertSpaces": true,
5 | "[csharp]": {
6 | "editor.rulers": [140]
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 0.1.0
4 |
5 | Initial Preview of PowerShell IoT
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.ADXL345/Microsoft.PowerShell.IoT.ADXL345.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 |
6 | # Root module file
7 | RootModule = 'Microsoft.PowerShell.IoT.ADXL345.psm1'
8 |
9 | # Version number of this module.
10 | ModuleVersion = '0.1.0'
11 |
12 | # ID used to uniquely identify this module
13 | GUID = '78f2d4bb-195e-4143-8f54-0a6d8c68612e'
14 |
15 | # Author of this module
16 | Author = 'Julien Nury'
17 |
18 | # Description of the functionality provided by this module
19 | Description = 'A set of functions to interact with ADXL345s accelerometer thru I2C'
20 |
21 | # Modules that must be imported into the global environment prior to importing this module
22 | RequiredModules = @('Microsoft.PowerShell.IoT')
23 |
24 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
25 | FunctionsToExport = 'Get-ADXL345Device', 'Get-ADXL345Data'
26 |
27 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
28 | CmdletsToExport = @()
29 |
30 | # Variables to export from this module
31 | VariablesToExport = @()
32 |
33 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
34 | AliasesToExport = @()
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.ADXL345/Microsoft.PowerShell.IoT.ADXL345.psm1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | # Inspired from https://github.com/sparkfun/SparkFun_ADXL345_Arduino_Library
5 |
6 | # Device registers and parameters
7 |
8 | $script:ADXL345_ADDRESS = 0x53 # I2c address
9 | $script:ADXL345_POWER_CTL = 0x2D # Power-Saving Features Control
10 | $script:ADXL345_DATAX0 = 0x32 # X-Axis Data 0
11 | $script:ADXL345_DATAX1 = 0x33 # X-Axis Data 1
12 | $script:ADXL345_DATAY0 = 0x34 # Y-Axis Data 0
13 | $script:ADXL345_DATAY1 = 0x35 # Y-Axis Data 1
14 | $script:ADXL345_DATAZ0 = 0x36 # Z-Axis Data 0
15 | $script:ADXL345_DATAZ1 = 0x37 # Z-Axis Data 1
16 | $script:ADXL345_GAINX = 0.00376390 # Gain to convert X value in g
17 | $script:ADXL345_GAINY = 0.00376009 # Gain to convert Y value in g
18 | $script:ADXL345_GAINZ = 0.00349265 # Gain to convert Z value in g
19 |
20 | # Published functions
21 | function Get-ADXL345Device {
22 | [CmdletBinding()]
23 | param
24 | (
25 | [ValidateNotNullOrEmpty()]
26 | [int]
27 | $Id = $script:ADXL345_ADDRESS,
28 |
29 | [ValidateNotNullOrEmpty()]
30 | [string]
31 | $FriendlyName = "ADXL345"
32 | )
33 |
34 | $Device = Get-I2CDevice -Id $Id -FriendlyName $FriendlyName
35 | InitializeDevice -Device $Device
36 | return $Device
37 | }
38 |
39 | function Get-ADXL345Data {
40 | param (
41 | [Parameter(ValueFromPipeline)]
42 | [ValidateNotNullOrEmpty()]
43 | [Microsoft.PowerShell.IoT.I2CDevice]
44 | $Device = (Get-ADXL345Device),
45 |
46 | [Parameter()]
47 | [Double]
48 | $Limit,
49 |
50 | [Switch]
51 | $Raw
52 | )
53 |
54 | try {
55 | $xValue0 = Get-I2CRegister -Device $Device -Register $script:ADXL345_DATAX0 -ByteCount 1
56 | $xValue1 = Get-I2CRegister -Device $Device -Register $script:ADXL345_DATAX1 -ByteCount 1
57 | $xValue = [int16]($xValue1.Data[0]) -shl 8 -bor [int16]($xValue0.Data[0])
58 |
59 | $yValue0 = Get-I2CRegister -Device $Device -Register $script:ADXL345_DATAY0 -ByteCount 1
60 | $yValue1 = Get-I2CRegister -Device $Device -Register $script:ADXL345_DATAY1 -ByteCount 1
61 | $yValue = [int16]($yValue1.Data[0]) -shl 8 -bor [int16]($yValue0.Data[0])
62 |
63 | $zValue0 = Get-I2CRegister -Device $Device -Register $script:ADXL345_DATAZ0 -ByteCount 1
64 | $zValue1 = Get-I2CRegister -Device $Device -Register $script:ADXL345_DATAZ1 -ByteCount 1
65 | $zValue = [int16]($zValue1.Data[0]) -shl 8 -bor [int16]($zValue0.Data[0])
66 | }
67 | catch {
68 | Throw "Unable to retreive data from device '$($Device.FriendlyName)'. Message: $($_.Exception.Message)"
69 | }
70 |
71 | if (-not $Raw) {
72 | $xValue = $xValue * $script:ADXL345_GAINX
73 | $yValue = $yValue * $script:ADXL345_GAINY
74 | $zValue = $zValue * $script:ADXL345_GAINZ
75 | }
76 |
77 | if ($Limit) {
78 | $xValue = FilterValue -Value $xValue -Maximum $Limit
79 | $yValue = FilterValue -Value $yValue -Maximum $Limit
80 | $zValue = FilterValue -Value $zValue -Maximum $Limit
81 | }
82 |
83 | return [PSObject]@{x = $xValue; y = $yValue; z = $zvalue}
84 | }
85 |
86 | # Internal functions
87 | function InitializeDevice {
88 | Param (
89 | [Parameter(Mandatory)]
90 | [Microsoft.PowerShell.IoT.I2CDevice]
91 | $Device
92 | )
93 |
94 | try {
95 | Set-I2CRegister -Device $Device -Register $script:ADXL345_POWER_CTL -Data 0x00
96 | Set-I2CRegister -Device $Device -Register $script:ADXL345_POWER_CTL -Data 0x10
97 | Set-I2CRegister -Device $Device -Register $script:ADXL345_POWER_CTL -Data 0x08
98 | }
99 | catch {
100 | Throw "Unable to initialize device '$($Device.FriendlyName)'. Message: $($_.Exception.Message)"
101 | }
102 | }
103 |
104 | function FilterValue {
105 | param (
106 | [Parameter(Mandatory)]
107 | [Double]
108 | $Value,
109 |
110 | [Parameter(Mandatory)]
111 | [Double]
112 | $Maximum
113 | )
114 |
115 | if ($Value -ge 0) {
116 | return [Math]::Min($value, $Maximum)
117 | } else {
118 | return [Math]::Max($Value, -$Maximum)
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.ADXL345/README.md:
--------------------------------------------------------------------------------
1 | # Example module Microsoft.PowerShell.IoT.ADXL345
2 |
3 | This PowerShell module is to interact with [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) for reading acceleration on 3 axis.
4 |
5 | ## Hardware setup
6 |
7 | Several vendors have breakout boards with ADXL345 sensor. In this example we'll use [SparkFun Triple Axis Accelerometer Breakout](https://www.sparkfun.com/products/9836).
8 |
9 | ADXL345 sensor supports both I2C and SPI interfaces; here we'll use I2C.
10 |
11 | Wiring diagram with Raspberry Pi 3 looks like this:
12 |
13 | 
14 |
15 | ## Software setup
16 |
17 | ### Install PowerShell Core on Raspberry Pi
18 |
19 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
20 |
21 | ### Enable I2C interface on Raspberry Pi
22 |
23 | 1. `sudo raspi-config`
24 | 2. `5 Interfacing options`
25 | 3. `P5 I2C`
26 | 4. `Would you like ARM I2C interface to be enabled -> Yes`
27 |
28 | ### Start Powershell and install modules
29 |
30 | **Don't forget to start PowerShell with sudo** or you'll be unable to access I2C bus.
31 |
32 | ```powershell
33 | sudo pwsh
34 | Install-Module -Name Microsoft.PowerShell.IoT
35 | git clone https://github.com/PowerShell/PowerShell-IoT.git
36 | Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.ADXL345
37 | ```
38 |
39 | ### Collect Data
40 |
41 | To simply collect acceleration values in g:
42 |
43 | ```powershell
44 | PS /home/pi> $accelerometer = Get-ADXL345Device
45 | PS /home/pi> Get-ADXL345Data -Device $accelerometer
46 |
47 | Name Value
48 | ---- -----
49 | y -0.03008072
50 | x 0.0828058
51 | z 0.86966985
52 | ```
53 |
54 | To represent current acceleration on the 3 axis with bargraphs:
55 |
56 | ```powershell
57 | PS /home/pi> $accelerometer = Get-ADXL345Device
58 | PS /home/pi> while ($true) {
59 | $data = Get-ADXL345Data -Device $accelerometer -Limit 1
60 | Write-Progress -id 1 -Activity 'X axis' -Status 'Acceleration' -PercentComplete ($data.x * 50 + 50)
61 | Write-Progress -id 2 -Activity 'Y axis' -Status 'Acceleration' -PercentComplete ($data.y * 50 + 50)
62 | Write-Progress -id 3 -Activity 'Z axis' -Status 'Acceleration' -PercentComplete ($data.z * 50 + 50)
63 | }
64 |
65 | X axis
66 | Acceleration
67 | [ooooooooooooooooooooooooooooooooooooooooooooooooooo ]
68 | Y axis
69 | Acceleration
70 | [ooooooooooooooooooooooooooooooooooooooooooooooooo ]
71 | Z axis
72 | Acceleration
73 | [ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ]
74 | ```
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.BME280/Microsoft.PowerShell.IoT.BME280.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 | GUID="eb74e8da-9ae2-482a-a648-e96550fb8739"
6 | Author="Microsoft Corporation"
7 | CompanyName="Microsoft Corporation"
8 | Copyright="© Microsoft Corporation. All rights reserved."
9 | Description='PowerShell module for working with Bosch Sensortec BME280 sensor.'
10 | ModuleVersion="0.1.0"
11 | FunctionsToExport = @('Get-BME280ChipID','Get-BME280Data','Get-BME280Device')
12 | CmdletsToExport = '*'
13 | AliasesToExport = @()
14 | NestedModules=@('Microsoft.PowerShell.IoT','Microsoft.PowerShell.IoT.BME280.psm1')
15 | HelpInfoURI = 'https://github.com/PowerShell/PowerShell-IoT'
16 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
17 | PrivateData = @{
18 | PSData = @{
19 | # Tags applied to this module. These help with module discovery in online galleries.
20 | Tags = 'IoT','RaspberryPi','Raspbian','BME280'
21 |
22 | # A URL to the license for this module.
23 | LicenseUri = 'https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt'
24 |
25 | # A URL to the main website for this project.
26 | ProjectUri = 'https://github.com/PowerShell/PowerShell-IoT'
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.BME280/Microsoft.PowerShell.IoT.BME280.psm1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | $script:CalibrationData = @{}
5 | $script:Device = $null
6 |
7 | # EXPORTED
8 |
9 | function Get-BME280Device
10 | {
11 | param
12 | (
13 | [ValidateNotNullOrEmpty()]
14 | [int]
15 | $Id = 0x77,
16 |
17 | [ValidateNotNullOrEmpty()]
18 | [string]
19 | $FriendlyName = "BME280"
20 | )
21 | $script:Device = Get-I2CDevice -Id $Id -FriendlyName $FriendlyName
22 | return $script:Device
23 | }
24 |
25 | function Get-BME280ChipID
26 | {
27 | param
28 | (
29 | [ValidateNotNullOrEmpty()]
30 | [Microsoft.PowerShell.IoT.I2CDevice]
31 | $Device = $script:Device
32 | )
33 | $Device = CreateDeviceIfNotExist -Device $Device
34 |
35 | return @{
36 | Device = $Device
37 | ChipId = Get-I2CRegister -Device $Device -Register 0xD0 -Raw
38 | }
39 | }
40 |
41 | # Units of returned data: temperature in degrees Celsius, pressure in hPa, relative humidity in %
42 | function Get-BME280Data
43 | {
44 | param
45 | (
46 | [Parameter(ValueFromPipeline=$true)]
47 | [ValidateNotNullOrEmpty()]
48 | [Microsoft.PowerShell.IoT.I2CDevice] $Device = $script:Device,
49 |
50 | [Parameter(Mandatory=$false)]
51 | [string] $Mode,
52 |
53 | [Parameter(Mandatory=$false)]
54 | [string] $Oversampling,
55 |
56 | [Parameter(Mandatory=$false)]
57 | [switch] $Fahrenheit
58 | )
59 | $Device = CreateDeviceIfNotExist -Device $Device
60 |
61 | Read-CalibrationData $Device
62 | Set-BME280Config $Device $Mode $Oversampling
63 |
64 | # read raw temperature, humidity and pressure measurement output data
65 | $adc = Get-I2CRegister -Device $Device -Register 0xF7 -ByteCount 8 -Raw
66 |
67 | [int] $adc_P = $adc[0]
68 | $adc_P = ($adc_P -shl 8) -bor $adc[1]
69 | $adc_P = ($adc_P -shl 4) -bor ($adc[2] -shr 4)
70 |
71 | [int] $adc_T = $adc[3]
72 | $adc_T = ($adc_T -shl 8) -bor $adc[4]
73 | $adc_T = ($adc_T -shl 4) -bor ($adc[5] -shr 4)
74 |
75 | [int] $adc_H = $adc[6]
76 | $adc_H = ($adc_H -shl 8) -bor $adc[7]
77 |
78 | [int] $TFine = Calc-T-Fine $adc_T $script:CalibrationData[$Device]
79 | [float] $Temperature = (($TFine * 5 + 128) -shr 8) / [float]100;
80 | if ($Fahrenheit)
81 | {
82 | $Temperature = $Temperature * 1.8 + 32
83 | }
84 |
85 | [float] $Pressure = Compensate_P $adc_P $script:CalibrationData[$Device] $TFine
86 | $Pressure = $Pressure / 100
87 |
88 | [float] $Humidity = Compensate_H $adc_H $script:CalibrationData[$Device] $TFine
89 | $Humidity = $Humidity / 100
90 |
91 | $result = [pscustomobject]@{
92 | Temperature=$Temperature;
93 | Pressure=$Pressure;
94 | Humidity=$Humidity}
95 |
96 | $result
97 | }
98 |
99 | # INTERNAL
100 |
101 | function CreateDeviceIfNotExist
102 | {
103 | param
104 | (
105 | [Microsoft.PowerShell.IoT.I2CDevice] $Device
106 | )
107 |
108 | if (-not $Device)
109 | {
110 | $script:Device = Get-BME280Device
111 | return $script:Device
112 | }
113 | return $Device
114 | }
115 |
116 | function Read-CalibrationData
117 | {
118 | param
119 | (
120 | [Parameter(Mandatory=$true)]
121 | [ValidateNotNullOrEmpty()]
122 | [Microsoft.PowerShell.IoT.I2CDevice] $Device
123 | )
124 |
125 | # read calibration data from sensor
126 | $cd1 = Get-I2CRegister -Device $Device -Register 0x88 -ByteCount 25 -Raw
127 | $cd2 = Get-I2CRegister -Device $Device -Register 0xE1 -ByteCount 7 -Raw
128 |
129 | [uint16] $T1 = $cd1[1]
130 | $T1 = ($T1 -shl 8) -bor $cd1[0]
131 |
132 | [int16] $T2 = $cd1[3]
133 | $T2 = ($T2 -shl 8) -bor $cd1[2]
134 |
135 | [int16] $T3 = $cd1[5]
136 | $T3 = ($T3 -shl 8) -bor $cd1[4]
137 |
138 | [uint16] $P1 = $cd1[7]
139 | $P1 = ($P1 -shl 8) -bor $cd1[6]
140 |
141 | [int16] $P2 = $cd1[9]
142 | $P2 = ($P2 -shl 8) -bor $cd1[8]
143 |
144 | [int16] $P3 = $cd1[11]
145 | $P3 = ($P3 -shl 8) -bor $cd1[10]
146 |
147 | [int16] $P4 = $cd1[13]
148 | $P4 = ($P4 -shl 8) -bor $cd1[12]
149 |
150 | [int16] $P5 = $cd1[15]
151 | $P5 = ($P5 -shl 8) -bor $cd1[14]
152 |
153 | [int16] $P6 = $cd1[17]
154 | $P6 = ($P6 -shl 8) -bor $cd1[16]
155 |
156 | [int16] $P7 = $cd1[19]
157 | $P7 = ($P7 -shl 8) -bor $cd1[18]
158 |
159 | [int16] $P8 = $cd1[21]
160 | $P8 = ($P8 -shl 8) -bor $cd1[20]
161 |
162 | [int16] $P9 = $cd1[23]
163 | $P9 = ($P9 -shl 8) -bor $cd1[22]
164 |
165 | [byte] $H1 = $cd1[24]
166 |
167 | [int16] $H2 = $cd2[1]
168 | $H2 = ($H2 -shl 8) -bor $cd2[0]
169 |
170 | [byte] $H3 = $cd2[2]
171 |
172 | [int16] $H4 = $cd2[3]
173 | $H4 = ($H4 -shl 4) -bor ($cd2[4] -band 0x00FF)
174 |
175 | [int16] $H5 = $cd2[5]
176 | $H5 = ($H5 -shl 4) -bor ($cd2[4] -band 0xFF00)
177 |
178 | [sbyte] $H6 = $cd2[6]
179 |
180 | $cd_final = [pscustomobject]@{
181 | T1=$T1;
182 | T2=$T2;
183 | T3=$T3;
184 |
185 | P1=$P1;
186 | P2=$P2;
187 | P3=$P3;
188 | P4=$P4;
189 | P5=$P5;
190 | P6=$P6;
191 | P7=$P7;
192 | P8=$P8;
193 | P9=$P9;
194 |
195 | H1=$H1;
196 | H2=$H2;
197 | H3=$H3;
198 | H4=$H4;
199 | H5=$H5;
200 | H6=$H6}
201 |
202 | $script:CalibrationData[$Device] = $cd_final
203 | }
204 |
205 | function Set-BME280Config
206 | {
207 | param
208 | (
209 | [Parameter(Mandatory=$true)]
210 | [ValidateNotNullOrEmpty()]
211 | [Microsoft.PowerShell.IoT.I2CDevice] $Device,
212 |
213 | [Parameter(Mandatory=$false)]
214 | [string] $Mode,
215 |
216 | [Parameter(Mandatory=$false)]
217 | [string] $Oversampling
218 | )
219 |
220 | # set oversampling of humidity data to ×2
221 | [byte] $reg_ctrl_hum = 0xF2
222 | [byte] $reg_ctrl_hum_value = [Convert]::ToByte("00000010",2)
223 |
224 | # set forced mode, set oversampling for temperature and pressure data to x2
225 | [byte] $reg_ctrl_meas = 0xF4
226 | [byte] $reg_ctrl_meas_value = [Convert]::ToByte("01001001",2)
227 |
228 | Set-I2CRegister -Device $Device -Register $reg_ctrl_hum -Data $reg_ctrl_hum_value
229 | Set-I2CRegister -Device $Device -Register $reg_ctrl_meas -Data $reg_ctrl_meas_value
230 | }
231 |
232 | # Calculate variable TFine (signed 32 bit) that carries a fine resolution temperature value over to the pressure and humidity compensation formula
233 | function Calc-T-Fine
234 | {
235 | param
236 | (
237 | [ValidateNotNullOrEmpty()]
238 | [int] $adc_T,
239 |
240 | [ValidateNotNullOrEmpty()]
241 | [pscustomobject] $cd
242 | )
243 |
244 | [int] $var1 = (((($adc_T -shr 3) - ([int]$cd.T1 -shl 1))) * ([int]$cd.T2)) -shr 11
245 | [int] $var2 = ((((($adc_T -shr 4) - ([int]$cd.T1)) * (($adc_T -shr 4) - ([int]$cd.T1))) -shr 12) * ([int]$cd.T3)) -shr 14
246 | [int] $TFine = $var1 + $var2
247 | $TFine
248 | }
249 |
250 | # Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
251 | # Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
252 | function Compensate_P
253 | {
254 | param
255 | (
256 | [ValidateNotNullOrEmpty()]
257 | [int] $adc_P,
258 |
259 | [ValidateNotNullOrEmpty()]
260 | [pscustomobject] $cd,
261 |
262 | [ValidateNotNullOrEmpty()]
263 | [int] $t_fine
264 | )
265 |
266 | [int64] $var1 = ([int64]$t_fine) - 128000;
267 | [int64] $var2 = $var1 * $var1 * [int64]$cd.P6;
268 | $var2 = $var2 + (($var1*[int64]$cd.P5) -shl 17);
269 | $var2 = $var2 + (([int64]$cd.P4) -shl 35);
270 | $var1 = (($var1 * $var1 * [int64]$cd.P3) -shr 8) + (($var1 * [int64]$cd.P2) -shl 12);
271 | $var1 = (((([int64]1) -shl 47)+$var1))*([int64]$cd.P1) -shr 33;
272 | if ($var1 -eq 0)
273 | {
274 | return 0 # avoid exception caused by division by zero
275 | }
276 | [int64] $p = 1048576 - $adc_P;
277 | $p = ((($p -shl 31)-$var2)*3125)/$var1;
278 | $var1 = (([int64]$cd.P9) * ($p -shr 13) * ($p -shr 13)) -shr 25;
279 | $var2 = (([int64]$cd.P8) * $p) -shr 19;
280 | $p = (($p + $var1 + $var2) -shr 8) + (([int64]$cd.P7) -shl 4);
281 | $p = [uint32]$p/256;
282 | $p
283 | }
284 |
285 | # Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
286 | # Output value of “47445” represents 47445/1024 = 46.333 %RH
287 | function Compensate_H
288 | {
289 | param
290 | (
291 | [ValidateNotNullOrEmpty()]
292 | [int] $adc_H,
293 |
294 | [ValidateNotNullOrEmpty()]
295 | [pscustomobject] $cd,
296 |
297 | [ValidateNotNullOrEmpty()]
298 | [int] $t_fine
299 | )
300 |
301 | [int32] $v_x1_u32r = ($t_fine - ([int32]76800))
302 | $v_x1_u32r = ((((($adc_H -shl 14) - (([int32]$cd.H4) -shl 20) - (([int32]$cd.H5) * $v_x1_u32r)) +
303 | ([int32]16384)) -shr 15) * ((((((($v_x1_u32r * ([int32]$cd.H6)) -shr 10) * ((($v_x1_u32r *
304 | ([int32]$cd.H3)) -shr 11) + ([int32]32768))) -shr 10) + ([int32]2097152)) *
305 | ([int32]$cd.H2) + 8192) -shr 14))
306 | $v_x1_u32r = ($v_x1_u32r - ((((($v_x1_u32r -shr 15) * ($v_x1_u32r -shr 15)) -shr 7) * ([int32]$cd.H1)) -shr 4))
307 | if ($v_x1_u32r -lt 0) { $v_x1_u32r = 0 }
308 | if ($v_x1_u32r -gt 419430400) {$v_x1_u32r = 419430400}
309 | $v_x1_u32r = ($v_x1_u32r -shr 12)*100 / 1024
310 | $v_x1_u32r
311 | }
312 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.BME280/README.md:
--------------------------------------------------------------------------------
1 | # Example module Microsoft.PowerShell.IoT.BME280
2 |
3 | This PowerShell module is for interacting with [BME280 environmental sensor](https://www.bosch-sensortec.com/bst/products/all_products/bme280) for reading temperature, pressure and humidity.
4 |
5 | ## Hardware setup
6 |
7 | Several vendors have breakout boards with BME280 sensor. In this example we'll use [BME280 breakout board from Adafruit](https://www.adafruit.com/product/2652).
8 |
9 | BME280 sensor supports both I2C and SPI interfaces; in this example we'll use I2C.
10 |
11 | Later, in the software section, we'll need to use I2C address of the BME280 sensor.
12 | The default I2C address is 0x77. It can be changed to 0x76 by connecting SDO to GND.
13 |
14 | Wiring diagram with Raspberry Pi 3 is like this:
15 |
16 | 
17 |
18 | ## Software setup
19 |
20 | ### Install PowerShell Core on Raspberry Pi
21 |
22 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
23 |
24 | ### Enable I2C interface on Raspberry Pi
25 |
26 | 1. `sudo raspi-config`
27 | 2. `5 Interfacing options`
28 | 3. `P5 I2C`
29 | 4. `Would you like ARM I2C interface to be enabled -> Yes`
30 |
31 | ### Start Powershell and install modules
32 |
33 | ```powershell
34 | sudo pwsh
35 | Install-Module -Name Microsoft.PowerShell.IoT
36 | git clone https://github.com/PowerShell/PowerShell-IoT.git
37 | Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.BME280
38 | ```
39 |
40 | ### Collect Data
41 | ```powershell
42 | PS /home/pi> $device = Get-BME280Device -Id 0x77 # I2C address of the sensor
43 | PS /home/pi> $data = Get-BME280Data -Device $device
44 | PS /home/pi> $data
45 |
46 | Temperature Pressure Humidity
47 | ----------- -------- --------
48 | 26.08 1009.41 29.21
49 |
50 | PS /home/pi> "Temperature in Fahrenheit = $($data.Temperature * 1.8 + 32)"
51 | Temperature in Fahrenheit = 76.69
52 | ```
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Fan/Microsoft.PowerShell.IoT.Fan.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 | GUID="0432ee36-7e87-4a21-814f-8feb17974647"
6 | Author="Microsoft Corporation"
7 | CompanyName="Microsoft Corporation"
8 | Copyright="© Microsoft Corporation. All rights reserved."
9 | Description='PowerShell module for controling a fan over GPIO.'
10 | ModuleVersion="0.1.0"
11 | FunctionsToExport = @('Enable-Fan','Disable-Fan')
12 | CmdletsToExport = @()
13 | AliasesToExport = @()
14 | RootModule = 'Microsoft.PowerShell.IoT.Fan.psm1'
15 | NestedModules=@('Microsoft.PowerShell.IoT')
16 | HelpInfoURI = 'https://github.com/PowerShell/PowerShell-IoT'
17 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
18 | PrivateData = @{
19 | PSData = @{
20 | # Tags applied to this module. These help with module discovery in online galleries.
21 | Tags = 'IoT','RaspberryPi','Raspbian'
22 |
23 | # A URL to the license for this module.
24 | LicenseUri = 'https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt'
25 |
26 | # A URL to the main website for this project.
27 | ProjectUri = 'https://github.com/PowerShell/PowerShell-IoT'
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Fan/Microsoft.PowerShell.IoT.Fan.psm1:
--------------------------------------------------------------------------------
1 | function Enable-Fan
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | [Parameter(Mandatory=$true, Position=0)]
7 | [ValidateNotNullOrEmpty()]
8 | [int] $Pin
9 | )
10 |
11 | Set-GpioPin -Id $Pin -Value High
12 | }
13 |
14 | function Disable-Fan
15 | {
16 | [CmdletBinding()]
17 | param
18 | (
19 | [Parameter(Mandatory=$true, Position=0)]
20 | [ValidateNotNullOrEmpty()]
21 | [int] $Pin
22 | )
23 |
24 | Set-GpioPin -Id $Pin -Value Low
25 | }
26 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Fan/README.md:
--------------------------------------------------------------------------------
1 | # Example module Microsoft.PowerShell.IoT.Fan
2 |
3 | This PowerShell module is for turning on/off a fan on Raspberry Pi 4 case enclosure.
4 | This showcases GPIO functionality of [the Microsoft.PowerShell.IoT module](../../README.md).
5 |
6 | ## Hardware setup
7 |
8 | [This Raspberry Pi 4 case enclosure](https://www.amazon.com/gp/product/B07XTRK8D4) comes with a 5V fan that can be connected to Raspberry Pi 5V and GND pins.
9 | This fan is nice but a little noisy so we can use this example module to turn it off when the CPU temperature is relatively low.
10 | An [IRLB8721 transistor](https://www.adafruit.com/product/355) can be used to switch power to the fan based on GPIO line of Raspberry Pi.
11 |
12 | ## Wiring
13 |
14 | Insert IRLB8721 transistor into the break of the negative wire of the fan.
15 | Connect transistor gate to GPIO 17 (BCM schema) on Raspberry Pi.
16 |
17 | 
18 | 
19 |
20 | ## Software setup
21 |
22 | ### Install PowerShell Core on Raspberry Pi
23 |
24 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
25 |
26 | ### Start Powershell and install modules
27 |
28 | ```powershell
29 | pwsh
30 |
31 | Install-Module -Name Microsoft.PowerShell.IoT
32 |
33 | git clone https://github.com/PowerShell/PowerShell-IoT.git
34 | ```
35 |
36 | ### Usage
37 |
38 | ```powershell
39 | # Start monitoring CPU temperature and turn on the fan when it reaches 71 degrees; turn fan off when CPU temperature drops below 55 degrees
40 | pwsh ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.Fan/SmartFan.ps1 -Pin 17 -OnTemperature 71 -OffTemperature 55 -TemperatureScale Celsius
41 | VERBOSE: 1:36:05 PM: CPU temperature = 71.575 C | 160.835 F
42 | VERBOSE: Starting fan...
43 | VERBOSE: 1:36:10 PM: CPU temperature = 70.601 C | 159.0818 F
44 | VERBOSE: 1:36:16 PM: CPU temperature = 70.114 C | 158.2052 F
45 | VERBOSE: 1:36:21 PM: CPU temperature = 68.653 C | 155.5754 F
46 | #...
47 | VERBOSE: 1:39:01 PM: CPU temperature = 55.504 C | 131.9072 F
48 | VERBOSE: 1:39:06 PM: CPU temperature = 55.504 C | 131.9072 F
49 | VERBOSE: 1:39:11 PM: CPU temperature = 54.043 C | 129.2774 F
50 | VERBOSE: Stopping fan...
51 | VERBOSE: 1:39:17 PM: CPU temperature = 55.991 C | 132.7838 F
52 | #...
53 | ```
54 |
55 | This produces following CPU temperature graph:
56 | 
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Fan/SmartFan.ps1:
--------------------------------------------------------------------------------
1 | param
2 | (
3 | [int] $Pin = 17,
4 | [int] $OnTemperature = 70,
5 | [int] $OffTemperature = 50,
6 | [ValidateSet("Fahrenheit","Celsius")]
7 | [string]$TemperatureScale = "Celsius",
8 | [int] $PollPeriodSeconds = 5
9 | )
10 |
11 | Import-Module $PSScriptRoot/Microsoft.PowerShell.IoT.Fan.psd1
12 |
13 | $OnTemperatureC = $OnTemperature
14 | $OffTemperatureC = $OffTemperature
15 | if ($TemperatureScale -eq "Fahrenheit")
16 | {
17 | $OnTemperatureC = ($OnTemperature - 32) * 5 / 9
18 | $OffTemperatureC = ($OffTemperature - 32) * 5 / 9
19 | }
20 |
21 | while($true)
22 | {
23 | $CpuTemperatureC = (Get-Content /sys/class/thermal/thermal_zone0/temp) / 1000
24 | $CpuTemperatureF = ($CpuTemperatureC * 9 / 5) + 32
25 |
26 | (Get-Date).ToString() + ": CPU temperature = $CpuTemperatureC C | $CpuTemperatureF F" | Write-Verbose
27 |
28 | if ($CpuTemperatureC -gt $OnTemperatureC)
29 | {
30 | "Starting fan..." | Write-Verbose
31 | Enable-Fan -Pin $Pin
32 | }
33 | elseif ($CpuTemperatureC -lt $OffTemperatureC)
34 | {
35 | "Stopping fan..." | Write-Verbose
36 | Disable-Fan -Pin $Pin
37 | }
38 |
39 | Start-Sleep -Seconds $PollPeriodSeconds
40 | }
41 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.LED/Microsoft.PowerShell.IoT.LED.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 | GUID="0432ee36-7e87-4a21-814f-8feb17974641"
6 | Author="Microsoft Corporation"
7 | CompanyName="Microsoft Corporation"
8 | Copyright="© Microsoft Corporation. All rights reserved."
9 | Description='PowerShell module for working with a single-color LED.'
10 | ModuleVersion="0.1.0"
11 | FunctionsToExport = @('Set-Led')
12 | CmdletsToExport = '*'
13 | AliasesToExport = @()
14 | NestedModules=@('Microsoft.PowerShell.IoT','Microsoft.PowerShell.IoT.LED.psm1')
15 | HelpInfoURI = 'https://github.com/PowerShell/PowerShell-IoT'
16 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
17 | PrivateData = @{
18 | PSData = @{
19 | # Tags applied to this module. These help with module discovery in online galleries.
20 | Tags = 'IoT','RaspberryPi','Raspbian','LED'
21 |
22 | # A URL to the license for this module.
23 | LicenseUri = 'https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt'
24 |
25 | # A URL to the main website for this project.
26 | ProjectUri = 'https://github.com/PowerShell/PowerShell-IoT'
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.LED/Microsoft.PowerShell.IoT.LED.psm1:
--------------------------------------------------------------------------------
1 | function Set-Led
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | [Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName="Pin")]
7 | [ValidateNotNullOrEmpty()]
8 | [string] $Pin,
9 |
10 | [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName="State")]
11 | [ValidateSet('On','Off',ignorecase=$true)]
12 | [string] $State
13 | )
14 | if ($State -eq 'On')
15 | {
16 | $value = "High"
17 | }
18 | else
19 | {
20 | $value = "Low"
21 | }
22 |
23 | Set-GpioPin -Id $Pin -Value $value
24 | }
25 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.LED/README.md:
--------------------------------------------------------------------------------
1 | # Example module Microsoft.PowerShell.IoT.LED
2 |
3 | This simple PowerShell module is for turning on/off a single color LED.
4 |
5 | 
6 |
7 | This showcases GPIO functionality of [the Microsoft.PowerShell.IoT module](../../README.md).
8 |
9 | ## Hardware setup
10 |
11 | Hardware pieces:
12 |
13 | * [Breadboard](https://en.wikipedia.org/wiki/Breadboard) (Optional)
14 | * Male to female [jumper wires](https://en.wikipedia.org/wiki/Jump_wire)
15 | * 1 270-330Ω resistor
16 | * A [single-color LED](http://upload.wikimedia.org/wikipedia/commons/e/e8/LEDs.jpg)
17 |
18 | ## Wiring diagram
19 |
20 | 
21 |
22 | ## Software setup
23 |
24 | ### Install PowerShell Core on Raspberry Pi
25 |
26 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
27 |
28 | ### Start Powershell and install modules
29 |
30 | ```powershell
31 | sudo pwsh
32 |
33 | Install-Module -Name Microsoft.PowerShell.IoT
34 |
35 | git clone https://github.com/PowerShell/PowerShell-IoT.git
36 |
37 | Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.LED
38 | ```
39 |
40 | ### Usage
41 |
42 | ```powershell
43 | # Turn LED on
44 | Set-Led -Pin 1 -State On
45 | # or
46 | Set-Led 1 On
47 | # or
48 | [PSCustomObject]@{Pin=1; State="On"} | Set-Led
49 |
50 | # Turn LED off
51 | Set-Led 1 Off
52 | ```
53 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Plant/Microsoft.PowerShell.IoT.Plant.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 | GUID="eb74e8da-9ae2-482a-a648-e96550fb8731"
6 | Author="Microsoft Corporation"
7 | CompanyName="Microsoft Corporation"
8 | Copyright="© Microsoft Corporation. All rights reserved."
9 | Description='PowerShell module for plant growth'
10 | ModuleVersion="0.1.0"
11 | FunctionsToExport = '*'
12 | CmdletsToExport = '*'
13 | AliasesToExport = @()
14 | NestedModules=@('Microsoft.PowerShell.IoT','Microsoft.PowerShell.IoT.Plant.psm1')
15 | HelpInfoURI = 'https://github.com/PowerShell/PowerShell-IoT'
16 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
17 | PrivateData = @{
18 | PSData = @{
19 | # Tags applied to this module. These help with module discovery in online galleries.
20 | Tags = 'IoT','RaspberryPi','Raspbian','Plant'
21 |
22 | # A URL to the license for this module.
23 | LicenseUri = 'https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt'
24 |
25 | # A URL to the main website for this project.
26 | ProjectUri = 'https://github.com/PowerShell/PowerShell-IoT'
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Plant/Microsoft.PowerShell.IoT.Plant.psm1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | function Read-SoilIsDry
5 | {
6 | $raw = Get-GpioPin -Id 5 -Raw
7 | if($raw -eq "High")
8 | {
9 | return $true
10 | }
11 | else
12 | {
13 | return $false
14 | }
15 | }
16 |
17 | function Set-Light
18 | {
19 | param
20 | (
21 | [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
22 | [ValidateSet('On','Off',ignorecase=$true)]
23 | [string] $State
24 | )
25 | if ($State -eq 'On')
26 | {
27 | $value = "High"
28 | }
29 | else
30 | {
31 | $value = "Low"
32 | }
33 |
34 | Set-GpioPin -Id 2 -Value $value
35 | }
36 |
37 | function Start-Water
38 | {
39 | Set-GpioPin -Id 0 -Value "Low"
40 | }
41 |
42 | function Stop-Water
43 | {
44 | Set-GpioPin -Id 0 -Value "High"
45 | }
46 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Plant/README.md:
--------------------------------------------------------------------------------
1 | # Example module Microsoft.PowerShell.IoT.Plant
2 |
3 | This PowerShell module is for automating taking care of potted indoor plants.
4 |
5 | This module allows a PowerShell script to control lights and water a plant when needed based on soil moisture level.
6 |
7 | This showcases GPIO functionality of [the Microsoft.PowerShell.IoT module](../../README.md).
8 |
9 | ## Hardware setup
10 |
11 | Hardware pieces:
12 |
13 | * For lights:
14 | * Desktop lamp
15 | * [Plant-specific light bulb](https://www.amazon.com/dp/B07567BPVH/ref=sspa_dk_detail_5?psc=1&pd_rd_i=B07567BPVH&pd_rd_wg=5iTv6&pd_rd_r=WYCAF6212XNJ9NQ14E5Q&pd_rd_w=2u0Gj)
16 | * [Power relay for power mains (for the lamp)](https://www.amazon.com/POWERSWITCHTAIL-COM-PowerSwitch-Tail-II/dp/B00B888VHM/ref=sr_1_1?ie=UTF8&qid=1518818881&sr=8-1)
17 | * For watering:
18 | * [Small water pump](https://www.adafruit.com/product/1150)
19 | * [Power Relay for 12V DC](https://www.ebay.com/itm/5V-2-Channel-Relay-Module-Shield-For-Arduino-PIC-ARM-DSP-AVR-Electronic-US/162876526032)
20 | * [12V DC PowerAdapter (for water pump)](https://www.adafruit.com/product/798)
21 | * [Soil moisture sensor](https://www.ebay.com/i/122408308563?chn=ps)
22 |
23 | Default pin configuration of Microsoft.PowerShell.IoT.Plant module:
24 |
25 | * Water pump relay connected to GPIO pin 0.
26 | * Light relay connected to GPIO pin 2.
27 | * Soil moisture sensor sends data to GPIO pin 5.
28 |
29 | Wiring diagram will be published shortly.
30 |
31 | ## Software setup
32 |
33 | ### Install PowerShell Core on Raspberry Pi
34 |
35 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
36 |
37 | ### Start Powershell and install modules
38 |
39 | ```powershell
40 | sudo pwsh
41 | Install-Module -Name Microsoft.PowerShell.IoT
42 | git clone https://github.com/PowerShell/PowerShell-IoT.git
43 | Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.Plant
44 | ```
45 |
46 | ### Manual operation
47 |
48 | ```powershell
49 | PS /home/pi> # working with light
50 | PS /home/pi> Set-Light On
51 | PS /home/pi> Set-Light Off
52 | PS /home/pi>
53 | PS /home/pi> # working with water
54 | PS /home/pi> Start-Water
55 | PS /home/pi> Stop-Water
56 | PS /home/pi>
57 | PS /home/pi> # reading soil moisture level
58 | PS /home/pi> Read-SoilIsDry
59 | ```
60 |
61 | ### Automated operation
62 |
63 | See `full-plant-demo.ps1`.
64 |
65 | This script runs 2 PS jobs - one controls light, the other - water.
66 |
67 | For demo purposes script runs for 2 minutes. Adjust timeouts in the script for your scenario.
68 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Plant/full-plant-demo.ps1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | # A demo that uses Jobs to toggle lights and turn on the pump
5 |
6 | Import-Module Microsoft.PowerShell.IoT.Plant
7 |
8 | $lightjob = Start-Job {
9 | Import-Module Microsoft.PowerShell.IoT.Plant
10 |
11 | # start with lights off
12 | Set-Light Off
13 | $lightsOn = $false
14 |
15 | while ($true) {
16 | # toggle lights
17 | $lightsOn = -not $lightsOn
18 | if ($lightsOn) {
19 | Set-Light On
20 | } else {
21 | Set-Light Off
22 | }
23 |
24 | # wait some amount of time before toggling again
25 | Start-Sleep -s 20
26 | }
27 | }
28 |
29 | $waterJob = Start-Job {
30 | Import-Module Microsoft.PowerShell.IoT.Plant
31 |
32 | # start with water off
33 | Stop-Water
34 |
35 | while ($true) {
36 |
37 | if (Read-SoilIsDry) {
38 |
39 | # turn on the water for some amount of time
40 | Start-Water
41 | Start-Sleep -s 20
42 | Stop-Water
43 |
44 | # wait some amount of time before checking again
45 | Start-Sleep -s 20
46 | }
47 |
48 | # check sensor every 10 seconds
49 | Start-Sleep -s 10
50 | }
51 | }
52 |
53 | # clean up
54 | Start-Sleep -s 120
55 | Stop-Job $lightJob
56 | Stop-Job $waterJob
57 |
58 | Stop-Water
59 | Set-Light Off
60 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.SSD1306/Microsoft.PowerShell.IoT.SSD1306.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 | GUID="eb74e8da-9ae2-482a-a648-e96550fb8741"
6 | Author="Microsoft Corporation"
7 | CompanyName="Microsoft Corporation"
8 | Copyright="© Microsoft Corporation. All rights reserved."
9 | Description='PowerShell module for working with SSD1306 I2C OLED display.'
10 | ModuleVersion="0.1.0"
11 | FunctionsToExport = @('New-OledDisplay','Set-OledText')
12 | CmdletsToExport = '*'
13 | AliasesToExport = @()
14 | NestedModules=@('Microsoft.PowerShell.IoT','Microsoft.PowerShell.IoT.SSD1306.psm1')
15 | HelpInfoURI = 'https://github.com/PowerShell/PowerShell-IoT'
16 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
17 | PrivateData = @{
18 | PSData = @{
19 | # Tags applied to this module. These help with module discovery in online galleries.
20 | Tags = 'IoT','RaspberryPi','Raspbian','SSD1306'
21 |
22 | # A URL to the license for this module.
23 | LicenseUri = 'https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt'
24 |
25 | # A URL to the main website for this project.
26 | ProjectUri = 'https://github.com/PowerShell/PowerShell-IoT'
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.SSD1306/Microsoft.PowerShell.IoT.SSD1306.psm1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | # Example usage:
5 | # New-OledDisplay | Set-OledText -Value "Hello from PowerShell"
6 |
7 | # SSD1306 datasheet can be found here:
8 | # https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
9 |
10 |
11 | # Several screen sizes are supported; select the right one
12 | $SSD1306_128_64 = 1
13 | $SSD1306_128_32 = 0
14 | $SSD1306_96_16 = 0
15 |
16 | $BLACK = 0
17 | $WHITE = 1
18 | $INVERSE = 2
19 |
20 | $SSD1306_SETCONTRAST = 0x81
21 | $SSD1306_DISPLAYALLOW_RESUME = 0xA4
22 | $SSD1306_DISPLAYALLON = 0xA5
23 | $SSD1306_NORMALDISPLAY = 0xA6
24 | $SSD1306_INVERTDISPLAY = 0xA7
25 | $SSD1306_DISPLAYOFF = 0xAE
26 | $SSD1306_DISPLAYON = 0xAF
27 | $SSD1306_SETDISPLAYOFFSET = 0xD3
28 | $SSD1306_SETCOMPINS = 0xDA
29 | $SSD1306_SETVCOMDETECT = 0xDB
30 | $SSD1306_SETDISPLAYCLOCKDIV = 0xD5
31 | $SSD1306_SETPRECHARGE = 0xD9
32 | $SSD1306_SETMULTIPLEX = 0xA8
33 | $SSD1306_SETLOWCOLUMN = 0x00
34 | $SSD1306_SETHIGHCOLUMN = 0x10
35 | $SSD1306_SETSTARTLINE = 0x40
36 | $SSD1306_MEMORYMODE = 0x20
37 | $SSD1306_COLUMNADDR = 0x21
38 | $SSD1306_PAGEADDR = 0x22
39 | $SSD1306_COMSCANINC = 0xC0
40 | $SSD1306_COMSCANDEC = 0xC8
41 | $SSD1306_SEGREMAP = 0xA0
42 | $SSD1306_CHARGEPUMP = 0x8D
43 | $SSD1306_EXTERNALVCC = 0x1
44 | $SSD1306_SWITCHCAPVCC = 0x2
45 | $SSD1306_ACTIVATE_SCROLL = 0x2F
46 | $SSD1306_DEACTIVATE_SCROLL = 0x2E
47 | $SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3
48 | $SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26
49 | $SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27
50 | $SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29
51 | $SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A
52 |
53 | if ($SSD1306_128_64)
54 | {
55 | $SSD1306_LCDWIDTH = 128
56 | $SSD1306_LCDHEIGHT = 64
57 | $WIDTH = 128
58 | $HEIGHT = 64
59 | }
60 | if ($SSD1306_128_32)
61 | {
62 | $SSD1306_LCDWIDTH = 128
63 | $SSD1306_LCDHEIGHT = 32
64 | $WIDTH = 128
65 | $HEIGHT = 32
66 | }
67 | if ($SSD1306_96_16)
68 | {
69 | $SSD1306_LCDWIDTH = 96
70 | $SSD1306_LCDHEIGHT = 16
71 | $WIDTH = 96
72 | $HEIGHT = 16
73 | }
74 |
75 | [int] $script:cursor_y = 0
76 | [int] $script:cursor_x = 0
77 | [int] $script:textsize = 1
78 | [int] $script:wrap = 1
79 |
80 | # memory buffer for the LCD
81 | $buffer = New-Object byte[] ($SSD1306_LCDWIDTH * $SSD1306_LCDHEIGHT / 8)
82 |
83 | function New-OledDisplay
84 | {
85 | param
86 | (
87 | [Parameter(Mandatory=$false)]
88 | [int] $Id = 0x3c,
89 |
90 | [Parameter(Mandatory=$false)]
91 | [string] $Name = "OLED"
92 | )
93 |
94 | $Device = Get-I2CDevice -Id $Id -FriendlyName $Name
95 |
96 | $vccstate = $SSD1306_SWITCHCAPVCC;
97 |
98 | # Init process
99 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_DISPLAYOFF
100 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETDISPLAYCLOCKDIV
101 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x80 # the suggested ratio 0x80
102 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETMULTIPLEX
103 | Set-I2CRegister -Device $Device -Register 0x00 -Data ($SSD1306_LCDHEIGHT - 1)
104 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETDISPLAYOFFSET # 0xD3
105 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x0
106 | Set-I2CRegister -Device $Device -Register 0x00 -Data ($SSD1306_SETSTARTLINE -bor 0x0)
107 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_CHARGEPUMP
108 | if ($vccstate -eq $SSD1306_EXTERNALVCC)
109 | {
110 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x10
111 | } else
112 | {
113 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x14
114 | }
115 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_MEMORYMODE
116 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x00
117 | Set-I2CRegister -Device $Device -Register 0x00 -Data ($SSD1306_SEGREMAP -bor 0x1)
118 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_COMSCANDEC
119 |
120 | if ($SSD1306_128_32)
121 | {
122 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETCOMPINS
123 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x02
124 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETCONTRAST
125 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x8F
126 | }
127 |
128 | if ($SSD1306_128_64)
129 | {
130 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETCOMPINS
131 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x12
132 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETCONTRAST
133 | if ($vccstate -eq $SSD1306_EXTERNALVCC)
134 | {
135 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x9F
136 | } else
137 | {
138 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0xCF
139 | }
140 | }
141 |
142 | if ($SSD1306_96_16)
143 | {
144 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETCOMPINS
145 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x2
146 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETCONTRAST
147 | if ($vccstate -eq $SSD1306_EXTERNALVCC)
148 | {
149 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x10
150 | } else
151 | {
152 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0xAF
153 | }
154 | }
155 |
156 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETPRECHARGE
157 | if ($vccstate -eq $SSD1306_EXTERNALVCC)
158 | {
159 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x22
160 | } else
161 | {
162 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0xF1
163 | }
164 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_SETVCOMDETECT
165 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0x40
166 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_DISPLAYALLOW_RESUME
167 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_NORMALDISPLAY
168 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_DEACTIVATE_SCROLL
169 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_DISPLAYON
170 |
171 | $Device
172 | }
173 |
174 | function ClearDisplay
175 | {
176 | [Array]::Clear($buffer, 0, $buffer.Length)
177 | $script:cursor_y = 0;
178 | $script:cursor_x = 0;
179 | }
180 |
181 | function Display
182 | {
183 | param
184 | (
185 | [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
186 | [ValidateNotNullOrEmpty()]
187 | [Microsoft.PowerShell.IoT.I2CDevice] $Device
188 | )
189 |
190 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_COLUMNADDR
191 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0 # Column start address (0 = reset)
192 | Set-I2CRegister -Device $Device -Register 0x00 -Data ($SSD1306_LCDWIDTH - 1) # Column end address
193 |
194 | Set-I2CRegister -Device $Device -Register 0x00 -Data $SSD1306_PAGEADDR
195 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0 # Page start address (0 = reset)
196 | if ($SSD1306_LCDHEIGHT -eq 64)
197 | {
198 | Set-I2CRegister -Device $Device -Register 0x00 -Data 7 # Page end address
199 | }
200 | if ($SSD1306_LCDHEIGHT -eq 32)
201 | {
202 | Set-I2CRegister -Device $Device -Register 0x00 -Data 3 # Page end address
203 | }
204 | if ($SSD1306_LCDHEIGHT -eq 16)
205 | {
206 | Set-I2CRegister -Device $Device -Register 0x00 -Data 1 # Page end address
207 | }
208 |
209 | for ($i = 0; $i -lt ($SSD1306_LCDWIDTH * $SSD1306_LCDHEIGHT / 8); $i++)
210 | {
211 | Set-I2CRegister -Device $Device -Register 0x40 -Data $buffer[$i]
212 | }
213 | }
214 |
215 |
216 | function DrawPixel
217 | {
218 | param
219 | (
220 | [int] $x,
221 | [int] $y,
222 | [int] $color
223 | )
224 |
225 | if (($x -lt 0) -or ($x -ge $WIDTH) -or ($y -lt 0) -or ($y -ge $HEIGHT))
226 | {
227 | return
228 | }
229 |
230 | # x column
231 | $i = $x + [math]::truncate($y / 8) * $SSD1306_LCDWIDTH
232 | if ($color -eq $WHITE)
233 | {
234 | $buffer[$i] = $buffer[$i] -bor (1 -shl ($y -band 7))
235 | }
236 | if ($color -eq $BLACK)
237 | {
238 | $buffer[$i] = $buffer[$i] -band -not(1 -shl ($y -band 7))
239 | }
240 | if ($color -eq $INVERSE)
241 | {
242 | $buffer[$i] = $buffer[$i] -bxor (1 -shl ($y -band 7));
243 | }
244 | }
245 |
246 | function DrawChar
247 | {
248 | param
249 | (
250 | [int] $x,
251 | [int] $y,
252 | [byte] $c,
253 | [int] $color,
254 | [int] $size
255 | )
256 |
257 |
258 | if (($x -ge $WIDTH) -or
259 | ($y -ge $HEIGHT) -or
260 | (($x + 6 * $size - 1) -lt 0) -or
261 | (($y + 8 * $size - 1) -lt 0))
262 | {
263 | return
264 | }
265 |
266 | for ($i = 0; $i -lt 6; $i++)
267 | {
268 | [byte] $line = 0
269 | if ($i -eq 5)
270 | {
271 | $line = 0x0
272 | }
273 | else
274 | {
275 | $line = $font[($c * 5) + $i]
276 | }
277 |
278 | for ($j = 0; $j -lt 8; $j++)
279 | {
280 | if ($line -band 0x1)
281 | {
282 | if ($size -eq 1) # default size
283 | {
284 | DrawPixel ($x + $i) ($y + $j) $color
285 | }
286 | }
287 | $line = $line -shr 1
288 | }
289 | }
290 | }
291 |
292 | function WriteChar
293 | {
294 | param
295 | (
296 | [byte] $c
297 | )
298 |
299 |
300 | if ($c -eq '\n')
301 | {
302 | $script:cursor_y += $script:textsize * 8
303 | $script:cursor_x = 0
304 | }
305 | else
306 | {
307 | if ($c -eq '\r')
308 | {
309 | // skip
310 | }
311 | else
312 | {
313 | DrawChar $script:cursor_x $script:cursor_y $c $WHITE $script:textsize
314 | $script:cursor_x += $script:textsize * 6
315 | if ($script:wrap -and ($script:cursor_x -gt ($WIDTH - $script:textsize * 6)))
316 | {
317 | $script:cursor_y += $script:textsize * 8
318 | $script:cursor_x = 0
319 | }
320 | }
321 | }
322 | }
323 |
324 | function Set-OledText
325 | {
326 | param
327 | (
328 | [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
329 | [ValidateNotNullOrEmpty()]
330 | [Microsoft.PowerShell.IoT.I2CDevice] $Device,
331 |
332 | [string] $Value
333 | )
334 |
335 | ClearDisplay
336 | $Value.ToCharArray() | %{ WriteChar $_ }
337 | Display $Device
338 | }
339 |
340 | # Standard ASCII 5x7 font Adaf
341 | [byte[]] $font = @(
342 | 0x00, 0x00, 0x00, 0x00, 0x00,
343 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
344 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
345 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
346 | 0x18, 0x3C, 0x7E, 0x3C, 0x18,
347 | 0x1C, 0x57, 0x7D, 0x57, 0x1C,
348 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
349 | 0x00, 0x18, 0x3C, 0x18, 0x00,
350 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
351 | 0x00, 0x18, 0x24, 0x18, 0x00,
352 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
353 | 0x30, 0x48, 0x3A, 0x06, 0x0E,
354 | 0x26, 0x29, 0x79, 0x29, 0x26,
355 | 0x40, 0x7F, 0x05, 0x05, 0x07,
356 | 0x40, 0x7F, 0x05, 0x25, 0x3F,
357 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
358 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
359 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
360 | 0x14, 0x22, 0x7F, 0x22, 0x14,
361 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
362 | 0x06, 0x09, 0x7F, 0x01, 0x7F,
363 | 0x00, 0x66, 0x89, 0x95, 0x6A,
364 | 0x60, 0x60, 0x60, 0x60, 0x60,
365 | 0x94, 0xA2, 0xFF, 0xA2, 0x94,
366 | 0x08, 0x04, 0x7E, 0x04, 0x08,
367 | 0x10, 0x20, 0x7E, 0x20, 0x10,
368 | 0x08, 0x08, 0x2A, 0x1C, 0x08,
369 | 0x08, 0x1C, 0x2A, 0x08, 0x08,
370 | 0x1E, 0x10, 0x10, 0x10, 0x10,
371 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
372 | 0x30, 0x38, 0x3E, 0x38, 0x30,
373 | 0x06, 0x0E, 0x3E, 0x0E, 0x06,
374 | 0x00, 0x00, 0x00, 0x00, 0x00,
375 | 0x00, 0x00, 0x5F, 0x00, 0x00,
376 | 0x00, 0x07, 0x00, 0x07, 0x00,
377 | 0x14, 0x7F, 0x14, 0x7F, 0x14,
378 | 0x24, 0x2A, 0x7F, 0x2A, 0x12,
379 | 0x23, 0x13, 0x08, 0x64, 0x62,
380 | 0x36, 0x49, 0x56, 0x20, 0x50,
381 | 0x00, 0x08, 0x07, 0x03, 0x00,
382 | 0x00, 0x1C, 0x22, 0x41, 0x00,
383 | 0x00, 0x41, 0x22, 0x1C, 0x00,
384 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
385 | 0x08, 0x08, 0x3E, 0x08, 0x08,
386 | 0x00, 0x80, 0x70, 0x30, 0x00,
387 | 0x08, 0x08, 0x08, 0x08, 0x08,
388 | 0x00, 0x00, 0x60, 0x60, 0x00,
389 | 0x20, 0x10, 0x08, 0x04, 0x02,
390 | 0x3E, 0x51, 0x49, 0x45, 0x3E,
391 | 0x00, 0x42, 0x7F, 0x40, 0x00,
392 | 0x72, 0x49, 0x49, 0x49, 0x46,
393 | 0x21, 0x41, 0x49, 0x4D, 0x33,
394 | 0x18, 0x14, 0x12, 0x7F, 0x10,
395 | 0x27, 0x45, 0x45, 0x45, 0x39,
396 | 0x3C, 0x4A, 0x49, 0x49, 0x31,
397 | 0x41, 0x21, 0x11, 0x09, 0x07,
398 | 0x36, 0x49, 0x49, 0x49, 0x36,
399 | 0x46, 0x49, 0x49, 0x29, 0x1E,
400 | 0x00, 0x00, 0x14, 0x00, 0x00,
401 | 0x00, 0x40, 0x34, 0x00, 0x00,
402 | 0x00, 0x08, 0x14, 0x22, 0x41,
403 | 0x14, 0x14, 0x14, 0x14, 0x14,
404 | 0x00, 0x41, 0x22, 0x14, 0x08,
405 | 0x02, 0x01, 0x59, 0x09, 0x06,
406 | 0x3E, 0x41, 0x5D, 0x59, 0x4E,
407 | 0x7C, 0x12, 0x11, 0x12, 0x7C,
408 | 0x7F, 0x49, 0x49, 0x49, 0x36,
409 | 0x3E, 0x41, 0x41, 0x41, 0x22,
410 | 0x7F, 0x41, 0x41, 0x41, 0x3E,
411 | 0x7F, 0x49, 0x49, 0x49, 0x41,
412 | 0x7F, 0x09, 0x09, 0x09, 0x01,
413 | 0x3E, 0x41, 0x41, 0x51, 0x73,
414 | 0x7F, 0x08, 0x08, 0x08, 0x7F,
415 | 0x00, 0x41, 0x7F, 0x41, 0x00,
416 | 0x20, 0x40, 0x41, 0x3F, 0x01,
417 | 0x7F, 0x08, 0x14, 0x22, 0x41,
418 | 0x7F, 0x40, 0x40, 0x40, 0x40,
419 | 0x7F, 0x02, 0x1C, 0x02, 0x7F,
420 | 0x7F, 0x04, 0x08, 0x10, 0x7F,
421 | 0x3E, 0x41, 0x41, 0x41, 0x3E,
422 | 0x7F, 0x09, 0x09, 0x09, 0x06,
423 | 0x3E, 0x41, 0x51, 0x21, 0x5E,
424 | 0x7F, 0x09, 0x19, 0x29, 0x46,
425 | 0x26, 0x49, 0x49, 0x49, 0x32,
426 | 0x03, 0x01, 0x7F, 0x01, 0x03,
427 | 0x3F, 0x40, 0x40, 0x40, 0x3F,
428 | 0x1F, 0x20, 0x40, 0x20, 0x1F,
429 | 0x3F, 0x40, 0x38, 0x40, 0x3F,
430 | 0x63, 0x14, 0x08, 0x14, 0x63,
431 | 0x03, 0x04, 0x78, 0x04, 0x03,
432 | 0x61, 0x59, 0x49, 0x4D, 0x43,
433 | 0x00, 0x7F, 0x41, 0x41, 0x41,
434 | 0x02, 0x04, 0x08, 0x10, 0x20,
435 | 0x00, 0x41, 0x41, 0x41, 0x7F,
436 | 0x04, 0x02, 0x01, 0x02, 0x04,
437 | 0x40, 0x40, 0x40, 0x40, 0x40,
438 | 0x00, 0x03, 0x07, 0x08, 0x00,
439 | 0x20, 0x54, 0x54, 0x78, 0x40,
440 | 0x7F, 0x28, 0x44, 0x44, 0x38,
441 | 0x38, 0x44, 0x44, 0x44, 0x28,
442 | 0x38, 0x44, 0x44, 0x28, 0x7F,
443 | 0x38, 0x54, 0x54, 0x54, 0x18,
444 | 0x00, 0x08, 0x7E, 0x09, 0x02,
445 | 0x18, 0xA4, 0xA4, 0x9C, 0x78,
446 | 0x7F, 0x08, 0x04, 0x04, 0x78,
447 | 0x00, 0x44, 0x7D, 0x40, 0x00,
448 | 0x20, 0x40, 0x40, 0x3D, 0x00,
449 | 0x7F, 0x10, 0x28, 0x44, 0x00,
450 | 0x00, 0x41, 0x7F, 0x40, 0x00,
451 | 0x7C, 0x04, 0x78, 0x04, 0x78,
452 | 0x7C, 0x08, 0x04, 0x04, 0x78,
453 | 0x38, 0x44, 0x44, 0x44, 0x38,
454 | 0xFC, 0x18, 0x24, 0x24, 0x18,
455 | 0x18, 0x24, 0x24, 0x18, 0xFC,
456 | 0x7C, 0x08, 0x04, 0x04, 0x08,
457 | 0x48, 0x54, 0x54, 0x54, 0x24,
458 | 0x04, 0x04, 0x3F, 0x44, 0x24,
459 | 0x3C, 0x40, 0x40, 0x20, 0x7C,
460 | 0x1C, 0x20, 0x40, 0x20, 0x1C,
461 | 0x3C, 0x40, 0x30, 0x40, 0x3C,
462 | 0x44, 0x28, 0x10, 0x28, 0x44,
463 | 0x4C, 0x90, 0x90, 0x90, 0x7C,
464 | 0x44, 0x64, 0x54, 0x4C, 0x44,
465 | 0x00, 0x08, 0x36, 0x41, 0x00,
466 | 0x00, 0x00, 0x77, 0x00, 0x00,
467 | 0x00, 0x41, 0x36, 0x08, 0x00,
468 | 0x02, 0x01, 0x02, 0x04, 0x02,
469 | 0x3C, 0x26, 0x23, 0x26, 0x3C,
470 | 0x1E, 0xA1, 0xA1, 0x61, 0x12,
471 | 0x3A, 0x40, 0x40, 0x20, 0x7A,
472 | 0x38, 0x54, 0x54, 0x55, 0x59,
473 | 0x21, 0x55, 0x55, 0x79, 0x41,
474 | 0x21, 0x54, 0x54, 0x78, 0x41,
475 | 0x21, 0x55, 0x54, 0x78, 0x40,
476 | 0x20, 0x54, 0x55, 0x79, 0x40,
477 | 0x0C, 0x1E, 0x52, 0x72, 0x12,
478 | 0x39, 0x55, 0x55, 0x55, 0x59,
479 | 0x39, 0x54, 0x54, 0x54, 0x59,
480 | 0x39, 0x55, 0x54, 0x54, 0x58,
481 | 0x00, 0x00, 0x45, 0x7C, 0x41,
482 | 0x00, 0x02, 0x45, 0x7D, 0x42,
483 | 0x00, 0x01, 0x45, 0x7C, 0x40,
484 | 0xF0, 0x29, 0x24, 0x29, 0xF0,
485 | 0xF0, 0x28, 0x25, 0x28, 0xF0,
486 | 0x7C, 0x54, 0x55, 0x45, 0x00,
487 | 0x20, 0x54, 0x54, 0x7C, 0x54,
488 | 0x7C, 0x0A, 0x09, 0x7F, 0x49,
489 | 0x32, 0x49, 0x49, 0x49, 0x32,
490 | 0x32, 0x48, 0x48, 0x48, 0x32,
491 | 0x32, 0x4A, 0x48, 0x48, 0x30,
492 | 0x3A, 0x41, 0x41, 0x21, 0x7A,
493 | 0x3A, 0x42, 0x40, 0x20, 0x78,
494 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
495 | 0x39, 0x44, 0x44, 0x44, 0x39,
496 | 0x3D, 0x40, 0x40, 0x40, 0x3D,
497 | 0x3C, 0x24, 0xFF, 0x24, 0x24,
498 | 0x48, 0x7E, 0x49, 0x43, 0x66,
499 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
500 | 0xFF, 0x09, 0x29, 0xF6, 0x20,
501 | 0xC0, 0x88, 0x7E, 0x09, 0x03,
502 | 0x20, 0x54, 0x54, 0x79, 0x41,
503 | 0x00, 0x00, 0x44, 0x7D, 0x41,
504 | 0x30, 0x48, 0x48, 0x4A, 0x32,
505 | 0x38, 0x40, 0x40, 0x22, 0x7A,
506 | 0x00, 0x7A, 0x0A, 0x0A, 0x72,
507 | 0x7D, 0x0D, 0x19, 0x31, 0x7D,
508 | 0x26, 0x29, 0x29, 0x2F, 0x28,
509 | 0x26, 0x29, 0x29, 0x29, 0x26,
510 | 0x30, 0x48, 0x4D, 0x40, 0x20,
511 | 0x38, 0x08, 0x08, 0x08, 0x08,
512 | 0x08, 0x08, 0x08, 0x08, 0x38,
513 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
514 | 0x2F, 0x10, 0x28, 0x34, 0xFA,
515 | 0x00, 0x00, 0x7B, 0x00, 0x00,
516 | 0x08, 0x14, 0x2A, 0x14, 0x22,
517 | 0x22, 0x14, 0x2A, 0x14, 0x08,
518 | 0xAA, 0x00, 0x55, 0x00, 0xAA,
519 | 0xAA, 0x55, 0xAA, 0x55, 0xAA,
520 | 0x00, 0x00, 0x00, 0xFF, 0x00,
521 | 0x10, 0x10, 0x10, 0xFF, 0x00,
522 | 0x14, 0x14, 0x14, 0xFF, 0x00,
523 | 0x10, 0x10, 0xFF, 0x00, 0xFF,
524 | 0x10, 0x10, 0xF0, 0x10, 0xF0,
525 | 0x14, 0x14, 0x14, 0xFC, 0x00,
526 | 0x14, 0x14, 0xF7, 0x00, 0xFF,
527 | 0x00, 0x00, 0xFF, 0x00, 0xFF,
528 | 0x14, 0x14, 0xF4, 0x04, 0xFC,
529 | 0x14, 0x14, 0x17, 0x10, 0x1F,
530 | 0x10, 0x10, 0x1F, 0x10, 0x1F,
531 | 0x14, 0x14, 0x14, 0x1F, 0x00,
532 | 0x10, 0x10, 0x10, 0xF0, 0x00,
533 | 0x00, 0x00, 0x00, 0x1F, 0x10,
534 | 0x10, 0x10, 0x10, 0x1F, 0x10,
535 | 0x10, 0x10, 0x10, 0xF0, 0x10,
536 | 0x00, 0x00, 0x00, 0xFF, 0x10,
537 | 0x10, 0x10, 0x10, 0x10, 0x10,
538 | 0x10, 0x10, 0x10, 0xFF, 0x10,
539 | 0x00, 0x00, 0x00, 0xFF, 0x14,
540 | 0x00, 0x00, 0xFF, 0x00, 0xFF,
541 | 0x00, 0x00, 0x1F, 0x10, 0x17,
542 | 0x00, 0x00, 0xFC, 0x04, 0xF4,
543 | 0x14, 0x14, 0x17, 0x10, 0x17,
544 | 0x14, 0x14, 0xF4, 0x04, 0xF4,
545 | 0x00, 0x00, 0xFF, 0x00, 0xF7,
546 | 0x14, 0x14, 0x14, 0x14, 0x14,
547 | 0x14, 0x14, 0xF7, 0x00, 0xF7,
548 | 0x14, 0x14, 0x14, 0x17, 0x14,
549 | 0x10, 0x10, 0x1F, 0x10, 0x1F,
550 | 0x14, 0x14, 0x14, 0xF4, 0x14,
551 | 0x10, 0x10, 0xF0, 0x10, 0xF0,
552 | 0x00, 0x00, 0x1F, 0x10, 0x1F,
553 | 0x00, 0x00, 0x00, 0x1F, 0x14,
554 | 0x00, 0x00, 0x00, 0xFC, 0x14,
555 | 0x00, 0x00, 0xF0, 0x10, 0xF0,
556 | 0x10, 0x10, 0xFF, 0x10, 0xFF,
557 | 0x14, 0x14, 0x14, 0xFF, 0x14,
558 | 0x10, 0x10, 0x10, 0x1F, 0x00,
559 | 0x00, 0x00, 0x00, 0xF0, 0x10,
560 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
561 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
562 | 0xFF, 0xFF, 0xFF, 0x00, 0x00,
563 | 0x00, 0x00, 0x00, 0xFF, 0xFF,
564 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
565 | 0x38, 0x44, 0x44, 0x38, 0x44,
566 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14,
567 | 0x7E, 0x02, 0x02, 0x06, 0x06,
568 | 0x02, 0x7E, 0x02, 0x7E, 0x02,
569 | 0x63, 0x55, 0x49, 0x41, 0x63,
570 | 0x38, 0x44, 0x44, 0x3C, 0x04,
571 | 0x40, 0x7E, 0x20, 0x1E, 0x20,
572 | 0x06, 0x02, 0x7E, 0x02, 0x02,
573 | 0x99, 0xA5, 0xE7, 0xA5, 0x99,
574 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
575 | 0x4C, 0x72, 0x01, 0x72, 0x4C,
576 | 0x30, 0x4A, 0x4D, 0x4D, 0x30,
577 | 0x30, 0x48, 0x78, 0x48, 0x30,
578 | 0xBC, 0x62, 0x5A, 0x46, 0x3D,
579 | 0x3E, 0x49, 0x49, 0x49, 0x00,
580 | 0x7E, 0x01, 0x01, 0x01, 0x7E,
581 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
582 | 0x44, 0x44, 0x5F, 0x44, 0x44,
583 | 0x40, 0x51, 0x4A, 0x44, 0x40,
584 | 0x40, 0x44, 0x4A, 0x51, 0x40,
585 | 0x00, 0x00, 0xFF, 0x01, 0x03,
586 | 0xE0, 0x80, 0xFF, 0x00, 0x00,
587 | 0x08, 0x08, 0x6B, 0x6B, 0x08,
588 | 0x36, 0x12, 0x36, 0x24, 0x36,
589 | 0x06, 0x0F, 0x09, 0x0F, 0x06,
590 | 0x00, 0x00, 0x18, 0x18, 0x00,
591 | 0x00, 0x00, 0x10, 0x10, 0x00,
592 | 0x30, 0x40, 0xFF, 0x01, 0x01,
593 | 0x00, 0x1F, 0x01, 0x01, 0x1E,
594 | 0x00, 0x19, 0x1D, 0x17, 0x12,
595 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
596 | 0x00, 0x00, 0x00, 0x00, 0x00)
597 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.SSD1306/README.md:
--------------------------------------------------------------------------------
1 | # Example module Microsoft.PowerShell.IoT.SSD1306
2 |
3 | This PowerShell module is for working with [small I2C OLED displays](https://www.ebay.com/itm/2X-0-96-I2C-IIC-Serial-128X64-LED-OLED-LCD-Display-Module-for-Arduino-White/191785893008?epid=2001476960&hash=item2ca7547c90:g:WbwAAOSwAPVZLOx~) based on [SSD1306 driver chip](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf).
4 |
5 | ## Hardware setup
6 |
7 | There are many versions of small OLED displays; in this example we'll use a 128x64 version based on I2C interface.
8 |
9 | Wiring diagram with Raspberry Pi 3 is like this:
10 |
11 | 
12 |
13 | ## Software setup
14 |
15 | ### Install PowerShell Core on Raspberry Pi
16 |
17 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
18 |
19 | ### Enable I2C interface on Raspberry Pi
20 |
21 | 1. `sudo raspi-config`
22 | 2. `5 Interfacing options`
23 | 3. `P5 I2C`
24 | 4. `Would you like ARM I2C interface to be enabled -> Yes`
25 |
26 | ### Start Powershell and install modules
27 |
28 | ```powershell
29 | sudo pwsh
30 | Install-Module -Name Microsoft.PowerShell.IoT
31 | git clone https://github.com/PowerShell/PowerShell-IoT.git
32 | Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.SSD1306
33 | ```
34 |
35 | ### Run example
36 | ```powershell
37 | PS /home/pi> New-OledDisplay | Set-OledText -Value "Hello from PowerShell"
38 | ```
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Scroll_pHat/Microsoft.PowerShell.IoT.SadJoey.ps1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | Import-Module Microsoft.PowerShell.IoT
5 |
6 | [int]$DeviceAddress = 0x60
7 | ######### Configuration Register and Value #########
8 | [int]$ConfigurationRegisterAddress = 0x00
9 | [int]$ConfigurationRegisterValue = 0x1B
10 |
11 | ######### Data Registers and value #########
12 | [int[]]$DataRegisterAddress = 0x04 ..0x08
13 | [int[]]$values = 0x12,0x08,0x08,0x08,0x12
14 | ######### Brightness Register and value #########
15 | [int]$BrightnessRegisterAddress = 0x0D
16 | [int]$BrightnessRegisterValue = 0x08 #Lowest intensity
17 |
18 | ######### Get the device and set the Configuration Register
19 | $Device = Get-I2CDevice -Id $DeviceAddress -FriendlyName phat
20 | Set-I2CRegister -Device $Device -Register $ConfigurationRegisterAddress -Data $ConfigurationRegisterValue
21 |
22 | ######## Brightness #####
23 | Set-I2CRegister -Device $Device -Register $BrightnessRegisterAddress -Data $BrightnessRegisterValue
24 |
25 | ######### Write the #sadJoey pattern to the Data registers #########
26 | $i = 0
27 | foreach ($register in $DataRegisterAddress) {
28 | Set-I2CRegister -Device $Device -Register $register -Data $values[$i]
29 | $i++
30 | }
31 |
32 | #In order to update the registers, we need to write something to the column register, accoding to the datasheet: "A write operation of any 8-bit value to the Update Column Register is required to update the Data Registers"
33 | [int]$UpdateRegisterAddress = 0x0C
34 | [int]$UpdateValue = 0xFF
35 |
36 | #After executing this instruction, a Sad Joey should appear on your pHat :)
37 | Set-I2CRegister -Device $Device -Register $UpdateRegisterAddress -Data $UpdateValue
38 |
--------------------------------------------------------------------------------
/Examples/Microsoft.PowerShell.IoT.Scroll_pHat/README.md:
--------------------------------------------------------------------------------
1 | # Example on how to interact with Scroll pHat
2 |
3 | With this example, we will see how we can interact with [Scroll pHat](https://shop.pimoroni.com/products/scroll-phat).
4 |
5 | ## Information
6 |
7 | After reading the [driver's data sheet](http://www.issi.com/WW/pdf/31FL3730.pdf) we know the following:
8 |
9 | There are three "types" of registers: Configuration register, Update register and data registers.
10 | The configuration register value is set to have the expected behaviour of this pHat.
11 |
12 | There are 11 data registers, ranging from address 0x01 to 1x0B.
13 | Each register holds 1byte, but since ScrollPHat only has 5 lines, only 5bits are used.
14 | To set the LED on, you need to set the correspondent bits as 1, as example, to achieve the following:
15 |
16 | 
17 |
18 | we need to set the register 1 with data 0x0D (0000 1101).
19 |
20 | ## Software setup
21 |
22 | ### Install PowerShell Core on Raspberry Pi
23 |
24 | Installation instructions can be found [here](https://github.com/PowerShell/PowerShell/tree/master/docs/installation/linux.md#raspbian).
25 |
26 | ### Enable I2C interface on Raspberry Pi
27 |
28 | 1. `sudo raspi-config`
29 | 2. `5 Interfacing options`
30 | 3. `P5 I2C`
31 | 4. `Would you like ARM I2C interface to be enabled -> Yes`
32 |
33 | Start PowerShell (**with sudo, so that you can access the I2C bus**)
34 |
35 | ```powershell
36 | sudo pwsh
37 |
38 | git clone https://github.com/PowerShell/PowerShell-IoT.git #if you haven't already
39 | ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.Scroll_pHat/Microsoft.PowerShell.IoT.SadJoey.ps1
40 | ```
41 |
42 | After running this code, you should see a "Sad Joey" on your Scroll pHat.
43 |
44 | Note: What's "Sad Joey"? - #SadJoey became "popular" meme/hastag [on twitter](https://twitter.com/search?q=%23sadJoey&src=typd) during the #PSConfEU 2018
45 |
46 | This is what you should see:
47 |
48 | 
--------------------------------------------------------------------------------
/Examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | Example modules that leverage PowerShell IoT in a specific way.
4 |
5 | ## Table of Contents
6 |
7 | | Example | Difficulty | Type |
8 | |---------|------------|------|
9 | | [Microsoft.PowerShell.IoT.LED](/Examples/Microsoft.PowerShell.IoT.LED) | Easy | GPIO |
10 | | [Microsoft.PowerShell.IoT.Scroll_pHat](/Examples/Microsoft.PowerShell.IoT.Scroll_pHat) | Easy | I2C |
11 | | [Microsoft.PowerShell.IoT.BME280](/Examples/Microsoft.PowerShell.IoT.BME280) | Medium | I2C |
12 | | [Microsoft.PowerShell.IoT.SSD1306](/Examples/Microsoft.PowerShell.IoT.SSD1306) | Medium | I2C |
13 | | [Microsoft.PowerShell.IoT.ADXL345](/Examples/Microsoft.PowerShell.IoT.ADXL345) | Medium | I2C |
14 | | [Microsoft.PowerShell.Plant](/Examples/Microsoft.PowerShell.IoT.Plant) | Hard | GPIO |
15 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation.
2 |
3 | MIT License
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 |
--------------------------------------------------------------------------------
/Move-PSIoTBuild.ps1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | param (
5 | [Parameter(ValueFromPipeline=$true, Mandatory=$true)]
6 | [ValidateNotNullOrEmpty()]
7 | [string[]]
8 | $Ip,
9 |
10 | [Parameter()]
11 | [string[]]
12 | $WithExample,
13 |
14 | [Parameter()]
15 | [switch]
16 | $Build
17 | )
18 | begin {
19 | $sessions = @()
20 | }
21 |
22 | process {
23 | Write-Host "Connecting to $Ip"
24 | $sessions += New-PSSession -HostName $Ip -UserName pi
25 | }
26 |
27 | end {
28 | if ($Build) {
29 | Invoke-Build
30 | }
31 |
32 | $sessions | ForEach-Object {
33 | $session = $_
34 |
35 | # Should compress and decompress
36 | Copy-Item "$PSScriptRoot\out\Microsoft.PowerShell.IoT" "/usr/local/share/powershell/Modules/Microsoft.PowerShell.IoT" -Recurse -Force -ToSession $session
37 |
38 | if ($WithExample) {
39 | $WithExample | ForEach-Object {
40 | $path = "$PSScriptRoot\Examples\$_"
41 | if (Test-Path $path) {
42 | # Should compress and decompress
43 | Copy-Item $path "/usr/local/share/powershell/Modules" -Recurse -Force -ToSession $session
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerShell-IoT
2 |
3 | [](https://ci.appveyor.com/project/PowerShell/powershell-iot)
4 | [](https://travis-ci.com/PowerShell/PowerShell-IoT)
5 | [](https://www.powershellgallery.com/packages/Microsoft.PowerShell.IoT/)
6 |
7 | > Note: PowerShell IoT is still in Preview
8 |
9 | A PowerShell module for interacting with hardware sensors and devices using common protocols: GPIO, I2C & SPI.
10 |
11 | 
12 |
13 | ## Information
14 |
15 | ### Goals
16 |
17 | The main goal of this project is to provide a friendly interface for interacting with hardware sensors and devices using PowerShell.
18 |
19 | That said,
20 | it was built as close to the metal as possible to keep the library broad enough to cover a range of sensors and devices.
21 |
22 | The hope is that this module will be the foundation for other modules that will expose specific cmdlets for interacting with specific sensors and devices.
23 |
24 | For example, a cmdlet stack to turn on a light bulb might be:
25 |
26 | ```powershell
27 | > Set-Light On # Your user types this / you make this cmdlet
28 | > Set-GpioPin -Id 4 -Value High # You use this to make that^ / we make this cmdlet
29 | > # Our code that makes that^
30 | ```
31 |
32 | To see some examples of modules built on top of PowerShell IoT, see the [Examples folder](/Examples).
33 |
34 | ### Supported platforms
35 |
36 | #### Supported devices
37 |
38 | * Raspberry Pi 3
39 | * Raspberry Pi 2
40 |
41 | #### Supported operating systems
42 |
43 | * Raspbian Stretch
44 |
45 | ### Documentation & Examples
46 |
47 | Please see our [docs folder here](/docs) for an API reference, pin layout and other docs. For examples, checkout our [examples folder](/Examples).
48 |
49 | ### Dependencies
50 |
51 | This project relies on [.NET Core IoT Libraries](https://github.com/dotnet/iot).
52 | It is a .NET library for interacting with Raspberry Pi's IO functionality.
53 |
54 | ## Installation
55 |
56 | ### PowerShell Gallery
57 |
58 | You can grab the latest version of PowerShell IoT by running:
59 |
60 | ```powershell
61 | Install-Module Microsoft.PowerShell.IoT
62 | ```
63 |
64 | Please note that since this module works with Hardware, higher privileges are required (run PowerShell with `sudo`, or as `root` user)
65 |
66 | Then see the section on [running](#running).
67 |
68 | If you want to write a module that uses PowerShell IoT, include it in the `RequiredModules` field of your module manifest.
69 |
70 | ### GitHub releases
71 |
72 | You can also manually download the zipped up module from the [releases](https://github.com/PowerShell/PowerShell-IoT/releases).
73 |
74 | Then see the section on [running](#running).
75 |
76 | ### AppVeyor
77 |
78 | You can download the latest CI build from our [AppVeyor build here](https://ci.appveyor.com/project/PowerShell/powershell-iot).
79 | Go to the latest build, click on either of the images, then click on the artifacts tab.
80 | From there, you can download a zip of the latest CI build.
81 |
82 | Then see the section on [running](#running).
83 |
84 | ### From Source
85 |
86 | #### Prerequisites
87 |
88 | * [PowerShell Core 6 or greater](https://github.com/PowerShell/PowerShell/releases)
89 | * [.NET Core SDK 2.0 or greater](https://www.microsoft.com/net/download/)
90 | * [InvokeBuild](https://www.powershellgallery.com/packages/InvokeBuild/)
91 | * A supported device like a [Raspberry Pi 3](https://www.raspberrypi.org/) with [PowerShell Core 6 on it](https://github.com/powershell/powershell#get-powershell)
92 |
93 | #### Building
94 |
95 | _NOTE: You can't build on ARM devices at this time so you will need to build on another machine and copy the build to the device._
96 |
97 | 1. Clone/download the repo
98 | 2. run `./build.ps1 -Bootstrap` to see if you're missing any tooling
99 | 3. run `./build.ps1` to build
100 |
101 | At this point, you'll notice an `out` folder has been generated in the root of your repo.
102 | The project is ready to be deployed to your device.
103 |
104 | #### Deploying
105 |
106 | We have included a helper script, `Move-PSIoTBuild.ps1`,
107 | that will move the PowerShell IoT build over to your device.
108 | This copy uses PSRP over SSH so make sure you're able to connect to your pi this way.
109 | The `Microsoft.PowerShell.IoT` module will be copied to your `$env:PSModulePath` on your device.
110 | Here's an example:
111 |
112 | ```powershell
113 | Move-PSIoTBuild.ps1 -Ip 10.123.123.123 # IP address of device
114 | ```
115 |
116 | You can also easily copy examples in the `Examples` folder over using the `-WithExample` flag.
117 | Just give a list of examples you want to copy over and it will move those to you `$env:PSModulePath` along with `Microsoft.PowerShell.IoT`:
118 |
119 | ```powershell
120 | Move-PSIoTBuild.ps1 -Ip 10.123.123.123 -WithExample Microsoft.PowerShell.IoT.Plant,Microsoft.PowerShell.IoT.SSD1306
121 | ```
122 |
123 | Also, with the `-Build` parameter,
124 | it will build/test/package your project before moving it.
125 |
126 | _NOTE: If you'd rather not use the script, simply copy the `out/Microsoft.PowerShell.IoT` to your device to get started._
127 |
128 | #### Running
129 |
130 | Start PowerShell:
131 |
132 | ```powershell
133 | pwsh
134 | ```
135 |
136 | If you have the `Microsoft.PowerShell.IoT` module in your PSModulePath:
137 |
138 | ```powershell
139 | Import-Module Microsoft.PowerShell.IoT
140 | ```
141 |
142 | Alternatively, just import the `.psd1`:
143 |
144 | ```powershell
145 | Import-Module /path/to/Microsoft.PowerShell.IoT/Microsoft.PowerShell.IoT.psd1
146 | ```
147 |
148 | At this point you can now mess with the module:
149 |
150 | ```powershell
151 | Get-Command -Module Microsoft.PowerShell.IoT
152 | Get-GpioPin 2 # gets the data from GPIO pin 2
153 | ```
154 |
155 | #### Testing
156 |
157 | You can run tests, but they require a particular setup. Here is how you run them:
158 |
159 | ```powershell
160 | ./build.ps1 -Test
161 | ```
162 |
163 | The setup required:
164 |
165 | * For I2C: An [Adafruit BME280 I2C or SPI Temperature Humidity Pressure Sensor](https://www.adafruit.com/product/2652)
166 | * For GPIO: Bend pins 26 and 22 to touch each other or connect them in some way
167 | * For SPI: An [Adafruit LIS3DH Triple-Axis Accelerometer](https://www.adafruit.com/product/2809)
168 |
169 | We currently have a build agent that will deploy PR code onto a test Raspberry Pi and run the tests found in the `test` directory.
170 |
--------------------------------------------------------------------------------
/SimpleBuild.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [Parameter()]
3 | $Runtime = "linux-arm"
4 | )
5 |
6 | if ((Test-Path "$PSScriptRoot\out")) {
7 | Remove-Item -Path $PSScriptRoot\out -Recurse -Force
8 | }
9 |
10 | Push-Location "$PSScriptRoot\src\Microsoft.PowerShell.IoT"
11 | dotnet publish --runtime $Runtime
12 | Pop-Location
13 |
14 | New-Item -ItemType directory -Path $PSScriptRoot\out | Out-Null
15 | New-Item -ItemType directory -Path $PSScriptRoot\out\Microsoft.PowerShell.IoT | Out-Null
16 |
17 | $OutModulePath = "$PSScriptRoot\out\Microsoft.PowerShell.IoT"
18 |
19 | Copy-Item -Path "$PSScriptRoot\src\Microsoft.PowerShell.IoT\Microsoft.PowerShell.IoT.psd1" -Destination $OutModulePath -Force
20 | Copy-Item -Path "$PSScriptRoot\src\Microsoft.PowerShell.IoT\bin\Debug\netstandard2.0\$Runtime\publish\*" -Destination $OutModulePath -Force -Recurse
21 |
22 | "Build module location: $OutModulePath" | Write-Verbose -Verbose
23 |
24 | "Setting VSTS variable 'BuildOutDir' to '$OutModulePath'" | Write-Verbose -Verbose
25 | Write-Host "##vso[task.setvariable variable=BuildOutDir]$OutModulePath"
26 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | image:
2 | - Visual Studio 2015
3 | - Ubuntu
4 |
5 | build: off
6 |
7 | # Ignore testing a commit if only the README.md file changed
8 | # Or if various strings are found in the commit message: updated readme, update readme, update docs, update version, update appveyor
9 | skip_commits:
10 | files:
11 | - README.md
12 | message: /updated readme.*|update readme.*s|update docs.*|update version.*|update appveyor.*/
13 |
14 | branches:
15 | only:
16 | - master
17 |
18 | test_script:
19 | - pwsh: Install-Module InvokeBuild -Force -Scope CurrentUser; Invoke-Build
20 |
21 | artifacts:
22 | - path: out\Microsoft.PowerShell.IoT
23 | name: Microsoft.PowerShell.IoT
24 |
--------------------------------------------------------------------------------
/azure-pipelines-release.yml:
--------------------------------------------------------------------------------
1 | name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
2 |
3 | trigger: none
4 |
5 | resources:
6 | repositories:
7 | - repository: ComplianceRepo
8 | type: github
9 | endpoint: ComplianceGHRepo
10 | name: PowerShell/compliance
11 |
12 | variables:
13 | - name: PackageName
14 | value: 'Microsoft.PowerShell.IoT'
15 | - name: PackageVersion
16 | value: '0.2.0'
17 | - name: BuildOutDir
18 | value: ''
19 |
20 | stages:
21 | - stage: Build
22 | displayName: Build module
23 | pool:
24 | name: 1ES
25 | demands:
26 | - ImageOverride -equals PSMMS2019-Secure
27 | jobs:
28 | - job: BuildPkg
29 | displayName: Build module
30 | variables:
31 | - group: ESRP
32 | steps:
33 |
34 | - pwsh: |
35 | & $(Build.SourcesDirectory)\SimpleBuild.ps1
36 | displayName: Build Microsoft.PowerShell.IoT module
37 | condition: succeededOrFailed()
38 |
39 | - pwsh: |
40 | dir "$(BuildOutDir)\*" -Recurse
41 | displayName: Show BuildOutDirectory
42 |
43 | - template: Sbom.yml@ComplianceRepo
44 | parameters:
45 | BuildDropPath: "$(BuildOutDir)"
46 | Build_Repository_Uri: 'https://github.com/PowerShell/PowerShell-IoT'
47 | PackageName: $(PackageName)
48 | PackageVersion: $(PackageVersion)
49 |
50 | - pwsh: |
51 | dir "$(BuildOutDir)\*" -Recurse
52 | displayName: Show BuildOutDirectory
53 |
54 | - pwsh: |
55 | $signSrcPath = "$(BuildOutDir)"
56 | # Set signing src path variable
57 | $vstsCommandString = "vso[task.setvariable variable=signSrcPath]${signSrcPath}"
58 | Write-Host "sending " + $vstsCommandString
59 | Write-Host "##$vstsCommandString"
60 | $signOutPath = "$(Build.SourcesDirectory)\signed\Microsoft.PowerShell.IoT"
61 | $null = New-Item -ItemType Directory -Path $signOutPath
62 | # Set signing out path variable
63 | $vstsCommandString = "vso[task.setvariable variable=signOutPath]${signOutPath}"
64 | Write-Host "sending " + $vstsCommandString
65 | Write-Host "##$vstsCommandString"
66 | # Set path variable for guardian codesign validation
67 | $vstsCommandString = "vso[task.setvariable variable=GDN_CODESIGN_TARGETDIRECTORY]${signOutPath}"
68 | Write-Host "sending " + $vstsCommandString
69 | Write-Host "##$vstsCommandString"
70 | displayName: Setup variables for signing
71 |
72 | - template: EsrpSign.yml@ComplianceRepo
73 | parameters:
74 | # the folder which contains the binaries to sign
75 | buildOutputPath: $(signSrcPath)
76 | # the location to put the signed output
77 | signOutputPath: $(signOutPath)
78 | # the certificate ID to use
79 | certificateId: "CP-230012"
80 | # the file pattern to use, comma separated
81 | pattern: '*.psd1,Microsoft.PowerShell.IoT.dll'
82 |
83 | - pwsh: |
84 | Compress-Archive -Path "$(signOutPath)\*" -DestinationPath "$(System.ArtifactsDirectory)\Microsoft.PowerShell.IoT.zip"
85 | displayName: Create Microsoft.PowerShell.IoT.zip
86 |
87 | - publish: $(System.ArtifactsDirectory)\Microsoft.PowerShell.IoT.zip
88 | artifact: SignedModule
89 |
90 | - template: assembly-module-compliance.yml@ComplianceRepo
91 | parameters:
92 | # component-governance
93 | sourceScanPath: '$(signOutPath)'
94 | # credscan
95 | suppressionsFile: ''
96 | # TermCheck
97 | optionsRulesDBPath: ''
98 | optionsFTPath: ''
99 | # tsa-upload
100 | codeBaseName: 'Microsoft_PowerShell_IoT_2_14_2022'
101 | # selections
102 | APIScan: false # set to false when not using Windows APIs.
103 | # binskim
104 | AnalyzeTarget: '$(signOutPath)\Microsoft.PowerShell.IoT.dll'
105 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | #!/usr/bin/env pwsh
5 | param(
6 | [Parameter()]
7 | [switch]
8 | $Bootstrap,
9 |
10 | [Parameter()]
11 | [switch]
12 | $Clean,
13 |
14 | [Parameter()]
15 | [switch]
16 | $Test
17 | )
18 |
19 | $NeededTools = @{
20 | PowerShellCore = "PowerShell Core 6.0.0 or greater"
21 | DotNetSdk = "dotnet sdk 2.0 or greater"
22 | InvokeBuild = "InvokeBuild latest"
23 | }
24 |
25 | function needsPowerShellCore () {
26 | try {
27 | $powershellverison = (pwsh -v)
28 | } catch {
29 | return $true
30 | }
31 | return $false
32 | }
33 |
34 | function needsDotNetSdk () {
35 | try {
36 | $dotnetverison = (dotnet --version)
37 | } catch {
38 | return $true
39 | }
40 | return $false
41 | }
42 |
43 | function needsInvokeBuild () {
44 | if (Get-Module -ListAvailable -Name InvokeBuild) {
45 | return $false
46 | }
47 | return $true
48 | }
49 |
50 | function getMissingTools () {
51 | $missingTools = @()
52 |
53 | if (needsPowerShellCore) {
54 | $missingTools += $NeededTools.PowerShellCore
55 | }
56 | if (needsDotNetSdk) {
57 | $missingTools += $NeededTools.DotNetSdk
58 | }
59 | if (needsInvokeBuild) {
60 | $missingTools += $NeededTools.InvokeBuild
61 | }
62 |
63 | return $missingTools
64 | }
65 |
66 | function hasMissingTools () {
67 | return ((getMissingTools).Count -gt 0)
68 | }
69 |
70 | if ($Bootstrap) {
71 | $string = "Here is what your environment is missing:`n"
72 | $missingTools = getMissingTools
73 | if (($missingTools).Count -eq 0) {
74 | $string += "* nothing!`n`n Run this script without a flag to build or a -Clean to clean."
75 | } else {
76 | $missingTools | ForEach-Object {$string += "* $_`n"}
77 | $string += "`nAll instructions for installing these tools can be found on PowerShell Editor Services' Github:`n" `
78 | + "https://github.com/powershell/PowerShellEditorServices#development"
79 | }
80 | Write-Host "`n$string`n"
81 | } elseif(hasMissingTools) {
82 | Write-Host "You are missing needed tools. Run './build.ps1 -Bootstrap' to see what they are."
83 | } else {
84 | if($Clean) {
85 | Invoke-Build Clean
86 | }
87 |
88 | Invoke-Build Package
89 |
90 | if($Test) {
91 | Invoke-Build Test
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Documentation on PowerShell IoT
2 |
3 | This folder contains documentation on how to get started with PowerShell IoT and general usage. For examples, go [here](/Examples)!
4 |
5 | ## Table of contents
6 |
7 | * [Raspberry Pi 3 Pin layout](/docs/rpi3_pin_layout.md)
8 | * [Remoting via SSH](/docs/remoting.md)
9 | * [API reference](/docs/api_reference.md)
10 |
--------------------------------------------------------------------------------
/docs/help/Get-GpioPin.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: Microsoft.PowerShell.IoT.dll-Help.xml
3 | Module Name: Microsoft.PowerShell.IoT
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-GpioPin
9 |
10 | ## SYNOPSIS
11 | Reads data from a GPIO pin.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Get-GpioPin [[-Id] ] [[-PullMode] ] [-Raw] []
17 | ```
18 |
19 | ## DESCRIPTION
20 |
21 | Reads data from a GPIO pin.
22 |
23 | ## EXAMPLES
24 |
25 | ### Example 1 - Read raw data from a GPIO pin
26 |
27 | ```powershell
28 | $raw = Get-GpioPin -Id 5 -Raw
29 | ```
30 |
31 | ## PARAMETERS
32 |
33 | ### -Id
34 |
35 | The ID number of the pin to be read.
36 |
37 | ```yaml
38 | Type: Int32[]
39 | Parameter Sets: (All)
40 | Aliases:
41 |
42 | Required: False
43 | Position: 0
44 | Default value: None
45 | Accept pipeline input: True (ByPropertyName, ByValue)
46 | Accept wildcard characters: False
47 | ```
48 |
49 | ### -PullMode
50 |
51 | Specifies the mode to use when reading the data. Possible values are: **Off**, **PullDown**,
52 | **PullUp**. Consult the documentation of your chipset to determine the requirements.
53 |
54 | ```yaml
55 | Type: PullMode
56 | Parameter Sets: (All)
57 | Aliases:
58 | Accepted values: Off, PullDown, PullUp
59 |
60 | Required: False
61 | Position: 1
62 | Default value: None
63 | Accept pipeline input: True (ByPropertyName)
64 | Accept wildcard characters: False
65 | ```
66 |
67 | ### -Raw
68 |
69 | When this switch is used, the cmdlet only returns a pin state value of **High** or **Low**.
70 |
71 | ```yaml
72 | Type: SwitchParameter
73 | Parameter Sets: (All)
74 | Aliases:
75 |
76 | Required: False
77 | Position: Named
78 | Default value: None
79 | Accept pipeline input: True (ByPropertyName)
80 | Accept wildcard characters: False
81 | ```
82 |
83 | ### CommonParameters
84 |
85 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
86 | -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose,
87 | -WarningAction, and -WarningVariable. For more information, see
88 | [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
89 |
90 | ## INPUTS
91 |
92 | ### System.Int32[]
93 |
94 | ### System.Nullable`1[[Microsoft.PowerShell.IoT.PullMode, Microsoft.PowerShell.IoT, Version=0.1.1.0, Culture=neutral, PublicKeyToken=null]]
95 |
96 | ### System.Management.Automation.SwitchParameter
97 |
98 | ## OUTPUTS
99 |
100 | ### System.Object
101 |
102 | ## NOTES
103 |
104 | ## RELATED LINKS
105 |
106 | [Set-GpioPin](Set-GpioPin.md)
107 |
--------------------------------------------------------------------------------
/docs/help/Get-I2CDevice.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: Microsoft.PowerShell.IoT.dll-Help.xml
3 | Module Name: Microsoft.PowerShell.IoT
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-I2CDevice
9 |
10 | ## SYNOPSIS
11 | Returns an **I2CDevice** object.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Get-I2CDevice [-Id] [[-FriendlyName] ] []
17 | ```
18 |
19 | ## DESCRIPTION
20 |
21 | Returns an **I2CDevice** object.}
22 |
23 | ## EXAMPLES
24 |
25 | ### Example 1 - Get an I2C device object
26 |
27 | ```powershell
28 | $Device = Get-I2CDevice -Id $Id -FriendlyName $FriendlyName
29 | ```
30 |
31 | ## PARAMETERS
32 |
33 | ### -FriendlyName
34 |
35 | The friendly name of the device.
36 |
37 | ```yaml
38 | Type: String
39 | Parameter Sets: (All)
40 | Aliases:
41 |
42 | Required: False
43 | Position: 1
44 | Default value: None
45 | Accept pipeline input: True (ByPropertyName)
46 | Accept wildcard characters: False
47 | ```
48 |
49 | ### -Id
50 |
51 | The I2c address of the device.
52 |
53 | ```yaml
54 | Type: Int32
55 | Parameter Sets: (All)
56 | Aliases:
57 |
58 | Required: True
59 | Position: 0
60 | Default value: None
61 | Accept pipeline input: True (ByPropertyName)
62 | Accept wildcard characters: False
63 | ```
64 |
65 | ### CommonParameters
66 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
67 | -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose,
68 | -WarningAction, and -WarningVariable. For more information, see
69 | [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
70 |
71 | ## INPUTS
72 |
73 | ### System.Int32
74 |
75 | ### System.String
76 |
77 | ## OUTPUTS
78 |
79 | ### System.Object
80 |
81 | ## NOTES
82 |
83 | ## RELATED LINKS
84 |
--------------------------------------------------------------------------------
/docs/help/Get-I2CRegister.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: Microsoft.PowerShell.IoT.dll-Help.xml
3 | Module Name: Microsoft.PowerShell.IoT
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Get-I2CRegister
9 |
10 | ## SYNOPSIS
11 | Reads the value of a register of an **I2CDevice**.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Get-I2CRegister [-Device] [-Register] [[-ByteCount] ] [-Raw]
17 | []
18 | ```
19 |
20 | ## DESCRIPTION
21 |
22 | Reads the value of a register of an **I2CDevice**.
23 |
24 | ## EXAMPLES
25 |
26 | ### Example 1 - Read the chip identifier from the register
27 |
28 | ```powershell
29 | $ChipId = Get-I2CRegister -Device $Device -Register 0xD0 -Raw
30 | ```
31 |
32 | ## PARAMETERS
33 |
34 | ### -ByteCount
35 |
36 | The number of bytes to be returned from the register.
37 |
38 | ```yaml
39 | Type: Byte
40 | Parameter Sets: (All)
41 | Aliases:
42 |
43 | Required: False
44 | Position: 2
45 | Default value: None
46 | Accept pipeline input: True (ByPropertyName)
47 | Accept wildcard characters: False
48 | ```
49 |
50 | ### -Device
51 |
52 | An **I2CDevice** object to be read from.
53 |
54 | ```yaml
55 | Type: I2CDevice
56 | Parameter Sets: (All)
57 | Aliases:
58 |
59 | Required: True
60 | Position: 0
61 | Default value: None
62 | Accept pipeline input: True (ByPropertyName, ByValue)
63 | Accept wildcard characters: False
64 | ```
65 |
66 | ### -Raw
67 |
68 | Returns only the value stored in the register rather than a **I2CDeviceRegisterData** object.
69 |
70 | ```yaml
71 | Type: SwitchParameter
72 | Parameter Sets: (All)
73 | Aliases:
74 |
75 | Required: False
76 | Position: Named
77 | Default value: None
78 | Accept pipeline input: True (ByPropertyName)
79 | Accept wildcard characters: False
80 | ```
81 |
82 | ### -Register
83 |
84 | The address of the register to be read.
85 |
86 | ```yaml
87 | Type: UInt16
88 | Parameter Sets: (All)
89 | Aliases:
90 |
91 | Required: True
92 | Position: 1
93 | Default value: None
94 | Accept pipeline input: True (ByPropertyName)
95 | Accept wildcard characters: False
96 | ```
97 |
98 | ### CommonParameters
99 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
100 | -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose,
101 | -WarningAction, and -WarningVariable. For more information, see
102 | [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
103 |
104 | ## INPUTS
105 |
106 | ### Microsoft.PowerShell.IoT.I2CDevice
107 |
108 | ### System.UInt16
109 |
110 | ### System.Byte
111 |
112 | ### System.Management.Automation.SwitchParameter
113 |
114 | ## OUTPUTS
115 |
116 | ### System.Object
117 |
118 | ## NOTES
119 |
120 | ## RELATED LINKS
121 |
--------------------------------------------------------------------------------
/docs/help/Microsoft.PowerShell.IoT.md:
--------------------------------------------------------------------------------
1 | ---
2 | Module Name: Microsoft.PowerShell.IoT
3 | Module Guid: eb74e8da-9ae2-482a-a648-e96550fb8745
4 | Download Help Link: {{ Update Download Link }}
5 | Help Version: {{ Please enter version of help manually (X.X.X.X) format }}
6 | Locale: en-US
7 | ---
8 |
9 | # Microsoft.PowerShell.IoT Module
10 |
11 | ## Description
12 |
13 | A PowerShell module for interacting with hardware sensors and devices using common protocols: GPIO,
14 | I2C & SPI.
15 |
16 | > Note: PowerShell IoT is still in Preview
17 |
18 | ## Microsoft.PowerShell.IoT Cmdlets
19 |
20 | ### [Get-GpioPin](Get-GpioPin.md)
21 | Reads data from a GPIO pin.
22 |
23 | ### [Get-I2CDevice](Get-I2CDevice.md)
24 | Returns an **I2CDevice** object.
25 |
26 | ### [Get-I2CRegister](Get-I2CRegister.md)
27 | Reads the value of a register of an **I2CDevice**.
28 |
29 | ### [Send-SPIData](Send-SPIData.md)
30 | Sends data on an Serial Peripheral Interface (SPI) channel.
31 |
32 | ### [Set-GpioPin](Set-GpioPin.md)
33 | Writes a value to a GPIO pin.
34 |
35 | ### [Set-I2CRegister](Set-I2CRegister.md)
36 | Writes a value to a register of an **I2CDevice**.
37 |
--------------------------------------------------------------------------------
/docs/help/Send-SPIData.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: Microsoft.PowerShell.IoT.dll-Help.xml
3 | Module Name: Microsoft.PowerShell.IoT
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Send-SPIData
9 |
10 | ## SYNOPSIS
11 | Sends data on an Serial Peripheral Interface (SPI) channel.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Send-SPIData [-Data] [[-Channel] ] [[-Frequency] ] [-Raw] []
17 | ```
18 |
19 | ## DESCRIPTION
20 |
21 | Sends data on an Serial Peripheral Interface (SPI) channel.
22 |
23 | ## EXAMPLES
24 |
25 | ### Example 1
26 |
27 | ```powershell
28 | PS C:\> {{ Add example code here }}
29 | ```
30 |
31 | {{ Add example description here }}
32 |
33 | ## PARAMETERS
34 |
35 | ### -Channel
36 |
37 | The channel number to be written to.
38 |
39 | ```yaml
40 | Type: UInt32
41 | Parameter Sets: (All)
42 | Aliases:
43 |
44 | Required: False
45 | Position: 1
46 | Default value: None
47 | Accept pipeline input: True (ByPropertyName)
48 | Accept wildcard characters: False
49 | ```
50 |
51 | ### -Data
52 |
53 | The data to be written to the channel.
54 |
55 | ```yaml
56 | Type: Byte[]
57 | Parameter Sets: (All)
58 | Aliases:
59 |
60 | Required: True
61 | Position: 0
62 | Default value: None
63 | Accept pipeline input: True (ByPropertyName, ByValue)
64 | Accept wildcard characters: False
65 | ```
66 |
67 | ### -Frequency
68 |
69 | The frequency in Hertz that is used to send data on the channel.
70 |
71 | ```yaml
72 | Type: UInt32
73 | Parameter Sets: (All)
74 | Aliases:
75 |
76 | Required: False
77 | Position: 2
78 | Default value: None
79 | Accept pipeline input: True (ByPropertyName)
80 | Accept wildcard characters: False
81 | ```
82 |
83 | ### -Raw
84 |
85 | Return the result code of the write operation rather than a full **SPIData** object.
86 |
87 | ```yaml
88 | Type: SwitchParameter
89 | Parameter Sets: (All)
90 | Aliases:
91 |
92 | Required: False
93 | Position: Named
94 | Default value: None
95 | Accept pipeline input: True (ByPropertyName)
96 | Accept wildcard characters: False
97 | ```
98 |
99 | ### CommonParameters
100 |
101 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
102 | -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose,
103 | -WarningAction, and -WarningVariable. For more information, see
104 | [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
105 |
106 | ## INPUTS
107 |
108 | ### System.Byte[]
109 |
110 | ### System.UInt32
111 |
112 | ### System.Management.Automation.SwitchParameter
113 |
114 | ## OUTPUTS
115 |
116 | ### System.Object
117 |
118 | ## NOTES
119 |
120 | ## RELATED LINKS
121 |
--------------------------------------------------------------------------------
/docs/help/Set-GpioPin.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: Microsoft.PowerShell.IoT.dll-Help.xml
3 | Module Name: Microsoft.PowerShell.IoT
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Set-GpioPin
9 |
10 | ## SYNOPSIS
11 | Writes a value to a GPIO pin.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Set-GpioPin [-Id] [-Value] [-PassThru] []
17 | ```
18 |
19 | ## DESCRIPTION
20 |
21 | Writes a value to a GPIO pin.
22 |
23 | ## EXAMPLES
24 |
25 | ### Example 1 - Write a value to a GPIO pin
26 |
27 | This example writes the value of a variable to GPIO pin 2.
28 |
29 | ```powershell
30 | Set-GpioPin -Id 2 -Value $value
31 | ```
32 |
33 | ### Example 2 - Set a GPIO pin state to **Low**
34 |
35 | This example sets the state of GPIO pin 0 to **Low**.
36 |
37 | ```powershell
38 | Set-GpioPin -Id 0 -Value "Low"
39 | ```
40 |
41 | ## PARAMETERS
42 |
43 | ### -Id
44 |
45 | The ID number of the pin to be written.
46 |
47 | ```yaml
48 | Type: Int32[]
49 | Parameter Sets: (All)
50 | Aliases:
51 |
52 | Required: True
53 | Position: 0
54 | Default value: None
55 | Accept pipeline input: True (ByPropertyName, ByValue)
56 | Accept wildcard characters: False
57 | ```
58 |
59 | ### -PassThru
60 |
61 | Normally this cmdlet does not return any output. When **PassThru** is used, the cmdlet returns a
62 | **PinData** object showing the value that was set.
63 |
64 | ```yaml
65 | Type: SwitchParameter
66 | Parameter Sets: (All)
67 | Aliases:
68 |
69 | Required: False
70 | Position: Named
71 | Default value: None
72 | Accept pipeline input: True (ByPropertyName)
73 | Accept wildcard characters: False
74 | ```
75 |
76 | ### -Value
77 |
78 | The value to set on the GPIO pin.
79 |
80 | ```yaml
81 | Type: SignalLevel
82 | Parameter Sets: (All)
83 | Aliases:
84 | Accepted values: Low, High
85 |
86 | Required: True
87 | Position: 1
88 | Default value: None
89 | Accept pipeline input: True (ByPropertyName)
90 | Accept wildcard characters: False
91 | ```
92 |
93 | ### CommonParameters
94 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
95 | -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose,
96 | -WarningAction, and -WarningVariable. For more information, see
97 | [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
98 |
99 | ## INPUTS
100 |
101 | ### System.Int32[]
102 |
103 | ### Microsoft.PowerShell.IoT.SignalLevel
104 |
105 | ### System.Management.Automation.SwitchParameter
106 |
107 | ## OUTPUTS
108 |
109 | ### System.Object
110 |
111 | ## NOTES
112 |
113 | ## RELATED LINKS
114 |
--------------------------------------------------------------------------------
/docs/help/Set-I2CRegister.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: Microsoft.PowerShell.IoT.dll-Help.xml
3 | Module Name: Microsoft.PowerShell.IoT
4 | online version:
5 | schema: 2.0.0
6 | ---
7 |
8 | # Set-I2CRegister
9 |
10 | ## SYNOPSIS
11 | Writes a value to a register of an **I2CDevice**.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Set-I2CRegister [-Device] [-Register] [-Data] [-PassThru] []
17 | ```
18 |
19 | ## DESCRIPTION
20 |
21 | Writes a value to a register of an **I2CDevice**.
22 |
23 | ## EXAMPLES
24 |
25 | ### Example 1
26 |
27 | ```powershell
28 | Set-I2CRegister -Device $Device -Register 0x00 -Data 0xF1
29 | ```
30 |
31 | ## PARAMETERS
32 |
33 | ### -Data
34 |
35 | The data to be written to the register.
36 |
37 | ```yaml
38 | Type: Byte[]
39 | Parameter Sets: (All)
40 | Aliases:
41 |
42 | Required: True
43 | Position: 2
44 | Default value: None
45 | Accept pipeline input: True (ByPropertyName)
46 | Accept wildcard characters: False
47 | ```
48 |
49 | ### -Device
50 |
51 | An **I2CDevice** object to be written to.
52 |
53 | ```yaml
54 | Type: I2CDevice
55 | Parameter Sets: (All)
56 | Aliases:
57 |
58 | Required: True
59 | Position: 0
60 | Default value: None
61 | Accept pipeline input: True (ByPropertyName, ByValue)
62 | Accept wildcard characters: False
63 | ```
64 |
65 | ### -PassThru
66 |
67 | Normally this cmdlet does not return any output. When **PassThru** is used, the cmdlet returns a
68 | **I2CDeviceRegisterData** object showing the value that was set.
69 |
70 | ```yaml
71 | Type: SwitchParameter
72 | Parameter Sets: (All)
73 | Aliases:
74 |
75 | Required: False
76 | Position: Named
77 | Default value: None
78 | Accept pipeline input: True (ByPropertyName)
79 | Accept wildcard characters: False
80 | ```
81 |
82 | ### -Register
83 |
84 | The address of the register to be written.
85 |
86 | ```yaml
87 | Type: UInt16
88 | Parameter Sets: (All)
89 | Aliases:
90 |
91 | Required: True
92 | Position: 1
93 | Default value: None
94 | Accept pipeline input: True (ByPropertyName)
95 | Accept wildcard characters: False
96 | ```
97 |
98 | ### CommonParameters
99 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable,
100 | -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose,
101 | -WarningAction, and -WarningVariable. For more information, see
102 | [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
103 |
104 | ## INPUTS
105 |
106 | ### Microsoft.PowerShell.IoT.I2CDevice
107 |
108 | ### System.UInt16
109 |
110 | ### System.Byte[]
111 |
112 | ### System.Management.Automation.SwitchParameter
113 |
114 | ## OUTPUTS
115 |
116 | ### System.Object
117 |
118 | ## NOTES
119 |
120 | ## RELATED LINKS
121 |
--------------------------------------------------------------------------------
/docs/remoting.md:
--------------------------------------------------------------------------------
1 | # SSH Remoting Docs
2 |
3 | > NOTE: These docs were created while using a Raspberry Pi 3 with Raspbian Stretch.
4 |
5 | ## Prereqs
6 |
7 | First you need to get the IP address of the device. You can do this by running this on the device:
8 |
9 | ```bash
10 | PS > hostname -I
11 |
12 | 123.123.123.123
13 | ```
14 |
15 | You also need to have [PowerShell Core](https://github.com/powershell/powershell) installed on your device.
16 |
17 | You'll also need some SSH client. macOS and linux have it installed by default, for Windows, check out the [Win32 port of OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH).
18 |
19 | ## Using pure SSH
20 |
21 | First ssh into your pi:
22 |
23 | ```plaintext
24 | > ssh pi@123.123.123.123
25 |
26 | # At this point you are remoted into to the device and can start PowerShell
27 |
28 | > sudo pwsh
29 | PS > Get-GpioPin 1
30 | ```
31 |
32 | ## Using PowerShell Remoting (PSRP) over SSH
33 |
34 | > NOTE: This will only work if your device doesn't require a password when you run `sudo pwsh`. The Raspberry Pi 3 with default configuration does not prompt.
35 |
36 | First you need to install [PowerShell Core](https://github.com/powershell/powershell) on your client machine. Windows PowerShell does not support PowerShell Remoting (PSRP) over SSH so that will not work.
37 |
38 | Second you need to set up PSRP over SSH. You can [follow this guide](https://github.com/PowerShell/PowerShell/blob/11631e7412197f3f803ebbef95a3ddb174a387ec/demos/SSHRemoting/README.md).
39 |
40 | When you get to the part where it says:
41 |
42 | > Add a PowerShell subsystem entry
43 |
44 | Put this:
45 |
46 | ```plaintext
47 | Subsystem powershell sudo pwsh -sshs -NoLogo -NoProfile
48 | ```
49 |
50 | Note the use of `sudo`.
51 |
52 | If done correctly, you should be able to run:
53 |
54 | ```powershell
55 | PS > Enter-PSSession -Hostname 123.123.123.123 -UserName pi
56 |
57 | # At this point you are remoted into to the device already in PowerShell
58 |
59 | [123.123.123.123] PS > Get-GpioPin 1
60 | ```
61 |
62 | By doing this, you should be able to automate working with your device using PowerShell 🎉
63 |
--------------------------------------------------------------------------------
/docs/rpi3_pin_layout.md:
--------------------------------------------------------------------------------
1 | # Pin layout
2 |
3 | PowerShell IoT uses logical representation of the microcontroller's GPIOs.
4 | Refer to the microcontroller's datasheet to find this information.
5 | In case of Raspberry Pi use the BCM number listed in the following diagram:
6 |
7 | ## Image reference
8 |
9 | 
10 |
11 | ## Text reference
12 |
13 | ```plaintext
14 | +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
15 | | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
16 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
17 | | | | 3.3v | | | 1 || 2 | | | 5v | | |
18 | | 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5v | | |
19 | | 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | |
20 | | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 0 | IN | TxD | 15 | 14 |
21 | | | | 0v | | | 9 || 10 | 1 | IN | RxD | 16 | 15 |
22 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 |
23 | | 27 | 2 | GPIO. 2 | OUT | 0 | 13 || 14 | | | 0v | | |
24 | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
25 | | | | 3.3v | | | 17 || 18 | 1 | IN | GPIO. 5 | 5 | 24 |
26 | | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | |
27 | | 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
28 | | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 |
29 | | | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 |
30 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
31 | | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | |
32 | | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 |
33 | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | |
34 | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
35 | | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 |
36 | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 |
37 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
38 | | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
39 | +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
40 | ```
--------------------------------------------------------------------------------
/psiot.build.ps1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | function NeedsRestore($rootPath) {
5 | # This checks to see if the number of folders under a given
6 | # path (like "src" or "test") is greater than the number of
7 | # obj\project.assets.json files found under that path, implying
8 | # that those folders have not yet been restored.
9 | $projectAssets = (Get-ChildItem "$rootPath\*\obj\project.assets.json")
10 | return ($projectAssets -eq $null) -or ((Get-ChildItem $rootPath).Length -gt $projectAssets.Length)
11 | }
12 |
13 | task Restore -If { "Restore" -in $BuildTask -or (NeedsRestore(".\src")) } {
14 | Push-Location $PSScriptRoot\src
15 | exec { dotnet restore }
16 | Pop-Location
17 | }
18 |
19 | task Clean Restore, {
20 | Push-Location $PSScriptRoot\src
21 | exec { dotnet clean }
22 | Pop-Location
23 | }
24 |
25 | task Build Restore, {
26 | Push-Location $PSScriptRoot\src
27 | exec { dotnet build }
28 | Pop-Location
29 | }
30 |
31 | task Test {
32 | Install-Module Pester -Force -Scope CurrentUser
33 | Push-Location $PSScriptRoot\test
34 | $res = Invoke-Pester -OutputFormat NUnitXml -OutputFile TestsResults.xml -PassThru
35 | if ($env:APPVEYOR) {
36 | (New-Object System.Net.WebClient).UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\TestsResults.xml));
37 | }
38 | if ($res.FailedCount -gt 0) { throw "$($res.FailedCount) tests failed."}
39 | Pop-Location
40 | }
41 |
42 | task Package Clean, Build, {
43 | if ((Test-Path "$PSScriptRoot\out")) {
44 | Remove-Item -Path $PSScriptRoot\out -Recurse -Force
45 | }
46 |
47 | Push-Location "$PSScriptRoot\src\Microsoft.PowerShell.IoT"
48 | dotnet publish
49 | Pop-Location
50 |
51 | New-Item -ItemType directory -Path $PSScriptRoot\out
52 | New-Item -ItemType directory -Path $PSScriptRoot\out\Microsoft.PowerShell.IoT
53 |
54 | Copy-Item -Path "$PSScriptRoot\src\Microsoft.PowerShell.IoT\Microsoft.PowerShell.IoT.psd1" -Destination "$PSScriptRoot\out\Microsoft.PowerShell.IoT\" -Force
55 | Copy-Item -Path "$PSScriptRoot\src\Microsoft.PowerShell.IoT\bin\Debug\netcoreapp2.0\publish\*" -Destination "$PSScriptRoot\out\Microsoft.PowerShell.IoT\" -Force -Recurse
56 |
57 | if ($env:TF_BUILD) {
58 | Import-Module "$PSScriptRoot\tools\vstsBuild.psm1"
59 | Publish-VstsBuildArtifact -ArtifactPath "$PSScriptRoot\out\Microsoft.PowerShell.IoT" -Bucket "Microsoft.PowerShell.IoT"
60 | }
61 | }
62 |
63 | # The default task is to run the entire CI build
64 | task . Package
65 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2003
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.PowerShell.IoT", "Microsoft.PowerShell.IoT\Microsoft.PowerShell.IoT.csproj", "{1AEC06E7-3F3E-4D45-A7CA-150F46C1C036}"
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 | {1AEC06E7-3F3E-4D45-A7CA-150F46C1C036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {1AEC06E7-3F3E-4D45-A7CA-150F46C1C036}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {1AEC06E7-3F3E-4D45-A7CA-150F46C1C036}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {1AEC06E7-3F3E-4D45-A7CA-150F46C1C036}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {2F50629C-F677-4660-A42C-ABAF9EE30D65}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/Gpio/Get/GetGpioPin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Management.Automation;
4 | using System.Device.Gpio;
5 |
6 | [Cmdlet(VerbsCommon.Get, "GpioPin")]
7 | public class GetGpioPin : GpioCmdletBase
8 | {
9 | [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0)]
10 | public int[] Id { get; set; }
11 |
12 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 1)]
13 | public PullMode? PullMode { get; set; }
14 |
15 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
16 | public SwitchParameter Raw { get; set; }
17 |
18 | protected override void ProcessRecord()
19 | {
20 | ArrayList pinList = new ArrayList();
21 |
22 | if ((this.Id == null) || (this.Id.Length <= 0))
23 | {
24 | // TODO: this is "gpio readall" functionality
25 | // do not forget to change Id param to Mandatory = false when this is implemented
26 | }
27 | else
28 | {
29 | pinList.AddRange(this.Id);
30 | }
31 |
32 | PinMode mode = PinMode.Input;
33 | if (this.PullMode.HasValue)
34 | {
35 | switch (this.PullMode.Value)
36 | {
37 | case global::PullMode.PullDown: mode = PinMode.InputPullDown; break;
38 | case global::PullMode.PullUp: mode = PinMode.InputPullUp; break;
39 | default: mode = PinMode.Input; break;
40 | };
41 | };
42 |
43 | foreach (int pinId in pinList)
44 | {
45 | SignalLevel slResult = SignalLevel.Low;
46 |
47 | this.EnsureOpenPin(pinId, mode);
48 |
49 | if (this.GpioController.Read(pinId) == PinValue.High)
50 | {
51 | slResult = SignalLevel.High;
52 | };
53 |
54 | if (this.Raw)
55 | {
56 | WriteObject(slResult);
57 | }
58 | else
59 | {
60 | GpioPinData pinData = new GpioPinData(pinId, slResult);
61 | WriteObject(pinData);
62 | }
63 | }
64 | }
65 | }
66 |
67 | public enum PullMode
68 | {
69 | Off = 0,
70 | PullDown = 1,
71 | PullUp = 2
72 | }
73 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/Gpio/GpioCmdletBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation;
3 | using System.Device.Gpio;
4 |
5 | public class GpioCmdletBase : Cmdlet
6 | {
7 | protected static GpioController StaticGpioController;
8 | protected GpioController GpioController
9 | {
10 | get
11 | {
12 | if (StaticGpioController == null)
13 | {
14 | StaticGpioController = new GpioController();
15 | }
16 | return StaticGpioController;
17 | }
18 | set
19 | {
20 | StaticGpioController = value;
21 | }
22 | }
23 |
24 | protected void EnsureOpenPin(int pinId, PinMode mode)
25 | {
26 | if (this.GpioController.IsPinOpen(pinId))
27 | {
28 | if (this.GpioController.GetPinMode(pinId) != mode)
29 | {
30 | this.GpioController.SetPinMode(pinId, mode);
31 | }
32 | }
33 | else
34 | {
35 | this.GpioController.OpenPin(pinId, mode);
36 | }
37 | }
38 | }
39 |
40 | [Cmdlet(VerbsCommon.Clear, "GpioResources")]
41 | public class ClearGpioResources : GpioCmdletBase
42 | {
43 | protected override void ProcessRecord()
44 | {
45 | if (GpioCmdletBase.StaticGpioController != null)
46 | {
47 | GpioCmdletBase.StaticGpioController.Dispose();
48 | GpioCmdletBase.StaticGpioController = null;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/Gpio/GpioPinData.cs:
--------------------------------------------------------------------------------
1 | public class GpioPinData
2 | {
3 | public int Id;
4 | public SignalLevel Value;
5 |
6 | public GpioPinData(int id, SignalLevel value)
7 | {
8 | this.Id = id;
9 | this.Value = value;
10 | }
11 | }
12 |
13 | public enum SignalLevel
14 | {
15 | Low = 0,
16 | High = 1
17 | }
18 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/Gpio/Set/SetGpioPin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation;
3 | using System.Device.Gpio;
4 |
5 | [Cmdlet(VerbsCommon.Set, "GpioPin")]
6 | public class SetGpioPin : GpioCmdletBase
7 | {
8 | [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0)]
9 | public int[] Id { get; set; }
10 |
11 | [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, Position = 1)]
12 | public SignalLevel Value { get; set; }
13 |
14 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
15 | public SwitchParameter PassThru { get; set; }
16 |
17 | protected override void ProcessRecord()
18 | {
19 | if (this.Id != null)
20 | {
21 | foreach (int pinId in this.Id)
22 | {
23 | this.EnsureOpenPin(pinId, PinMode.Output);
24 |
25 | if(this.Value == SignalLevel.Low)
26 | {
27 | this.GpioController.Write(pinId, PinValue.Low);
28 | }
29 | else
30 | {
31 | this.GpioController.Write(pinId, PinValue.High);
32 | }
33 |
34 | if (this.PassThru)
35 | {
36 | GpioPinData pinData = new GpioPinData(pinId, this.Value);
37 | WriteObject(pinData);
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/I2c/Get/GetI2cDevice.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation;
3 | using System.Device.I2c;
4 |
5 | [Cmdlet(VerbsCommon.Get, "I2CDevice")]
6 | public class GetI2CDevice : Cmdlet
7 | {
8 | [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, Position = 0)]
9 | public int Id { get; set; }
10 |
11 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 1)]
12 | public string FriendlyName { get; set; }
13 |
14 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 2)]
15 | public int BusId { get; set; }
16 |
17 | public GetI2CDevice()
18 | {
19 | this.FriendlyName = string.Empty;
20 | this.BusId = 1;
21 | }
22 |
23 | protected override void ProcessRecord()
24 | {
25 | var settings = new I2cConnectionSettings(this.BusId, this.Id);
26 | I2cDevice device = I2cDevice.Create(settings);
27 | WriteObject(new I2CDevice(device, this.Id, this.FriendlyName, this.BusId));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/I2c/Get/GetI2cRegister.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation; // PowerShell namespace.
3 | [Cmdlet(VerbsCommon.Get, "I2CRegister")]
4 | public class GetI2CRegister : Cmdlet
5 | {
6 | [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0)]
7 | public I2CDevice Device { get; set; }
8 |
9 | [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, Position = 1)]
10 | public ushort Register { get; set; }
11 |
12 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 2)]
13 | public byte ByteCount { get; set; }
14 |
15 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
16 | public SwitchParameter Raw { get; set; }
17 |
18 | public GetI2CRegister()
19 | {
20 | this.ByteCount = 1;
21 | this.Raw = false;
22 | }
23 |
24 | protected override void ProcessRecord()
25 | {
26 | if (this.ByteCount > 1)
27 | {
28 | Span readBuffer = stackalloc byte[ByteCount];
29 |
30 | this.Device.device.WriteByte((byte)this.Register);
31 | this.Device.device.Read(readBuffer);
32 |
33 | if (this.Raw)
34 | {
35 | WriteObject(readBuffer.ToArray());
36 | }
37 | else
38 | {
39 | I2CDeviceRegisterData result = new I2CDeviceRegisterData(this.Device, this.Register)
40 | {
41 | Data = readBuffer.ToArray() // optimize to be Span? How does PowerShell deal with it?
42 | };
43 | WriteObject(result);
44 | }
45 | }
46 | else
47 | {
48 | this.Device.device.WriteByte((byte)this.Register);
49 | byte value = this.Device.device.ReadByte();
50 | //byte value = this.Device.device.ReadAddressByte(this.Register);
51 | if (this.Raw)
52 | {
53 | WriteObject(value);
54 | }
55 | else
56 | {
57 | I2CDeviceRegisterData result = new I2CDeviceRegisterData(this.Device, this.Register, new byte[1] { value });
58 | WriteObject(result);
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/I2c/I2cDevice.cs:
--------------------------------------------------------------------------------
1 | public class I2CDevice
2 | {
3 | internal System.Device.I2c.I2cDevice device = null;
4 |
5 | public string FriendlyName { get; set; }
6 | public int Id { get; set; }
7 | public int BusId { get; set; }
8 |
9 | public I2CDevice(System.Device.I2c.I2cDevice device, int Id, string FriendlyName, int BusId)
10 | {
11 | this.device = device;
12 | this.Id = Id;
13 | this.FriendlyName = FriendlyName;
14 | this.BusId = BusId;
15 | }
16 |
17 | public override string ToString()
18 | {
19 | if (string.IsNullOrEmpty(this.FriendlyName))
20 | {
21 | return this.Id.ToString();
22 | }
23 | else
24 | {
25 | return this.FriendlyName;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/I2c/I2cRegisterData.cs:
--------------------------------------------------------------------------------
1 | public class I2CDeviceRegisterData
2 | {
3 | public I2CDevice Device { get; set; }
4 | public ushort Register { get; set; }
5 | public byte[] Data { get; set; }
6 |
7 | public I2CDeviceRegisterData(I2CDevice device, ushort register, byte[] data)
8 | {
9 | this.Device = device;
10 | this.Register = register;
11 | this.Data = data;
12 | }
13 |
14 | public I2CDeviceRegisterData(I2CDevice device, ushort register)
15 | : this(device, register, new byte[0])
16 | {
17 | }
18 |
19 | public I2CDeviceRegisterData()
20 | : this(null, 0)
21 | {
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/I2c/Set/SetI2cRegister.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation; // PowerShell namespace.
3 |
4 | [Cmdlet(VerbsCommon.Set, "I2CRegister")]
5 | public class SetI2CRegister : Cmdlet
6 | {
7 | [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0)]
8 | public I2CDevice Device { get; set; }
9 |
10 | [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, Position = 1)]
11 | public ushort Register { get; set; }
12 |
13 | [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, Position = 2)]
14 | public byte[] Data { get; set; }
15 |
16 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
17 | public SwitchParameter PassThru { get; set; }
18 |
19 | protected override void ProcessRecord()
20 | {
21 | Span dataOut = stackalloc byte[] { (byte)Register, Data[0] };
22 | this.Device.device.Write(dataOut);
23 | if (this.PassThru)
24 | {
25 | I2CDeviceRegisterData result = new I2CDeviceRegisterData(this.Device, this.Register, this.Data);
26 | WriteObject(result);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/Microsoft.PowerShell.IoT.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | 0.2.0.0
6 | Microsoft Corporation
7 | Microsoft Corporation
8 | Microsoft.PowerShell.IoT
9 | Microsoft.PowerShell.IoT
10 | 0.2.0.0
11 | 0.2.0.0
12 | © Microsoft Corporation. All rights reserved.
13 | https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt
14 | https://github.com/PowerShell/PowerShell-IoT
15 | https://github.com/PowerShell/PowerShell-IoT
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/Microsoft.PowerShell.IoT.psd1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | @{
5 | GUID="eb74e8da-9ae2-482a-a648-e96550fb8745"
6 | Author="Microsoft Corporation"
7 | CompanyName="Microsoft Corporation"
8 | Copyright="© Microsoft Corporation. All rights reserved."
9 | Description='A PowerShell module for interacting with hardware sensors and devices using common protocols: GPIO, I2C & SPI.'
10 | ModuleVersion="0.2.0"
11 | FunctionsToExport = '*'
12 | CmdletsToExport = '*'
13 | AliasesToExport = @()
14 | NestedModules=@('Microsoft.PowerShell.IoT.dll')
15 | HelpInfoURI = 'https://github.com/PowerShell/PowerShell-IoT'
16 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
17 | PrivateData = @{
18 | PSData = @{
19 | # Tags applied to this module. These help with module discovery in online galleries.
20 | Tags = 'IoT','RaspberryPi','Raspbian','GPIO','I2C','SPI'
21 |
22 | # A URL to the license for this module.
23 | LicenseUri = 'https://github.com/PowerShell/PowerShell-IoT/blob/master/LICENSE.txt'
24 |
25 | # A URL to the main website for this project.
26 | ProjectUri = 'https://github.com/PowerShell/PowerShell-IoT'
27 |
28 | # A URL to an icon representing this module.
29 | # IconUri = ''
30 |
31 | # ReleaseNotes of this module
32 | ReleaseNotes = '## 0.2.0
33 |
34 | Started using System.Device.Gpio
35 |
36 | ## 0.1.1
37 |
38 | Minor bug fixes
39 |
40 | ## 0.1.0
41 |
42 | Initial preview of PowerShell IoT
43 | '
44 | }
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/SPI/SPIData.cs:
--------------------------------------------------------------------------------
1 | public class SPIData
2 | {
3 | public int BusId { get; set; }
4 | public int ChipSelectLine { get; set; }
5 | public int Frequency { get; set; }
6 | public byte[] Data { get; set; }
7 | public byte[] Response { get; set; }
8 |
9 | public SPIData(int busId, int chipSelectLine, int frequency, byte[] data, byte[] response)
10 | {
11 | this.BusId = busId;
12 | this.ChipSelectLine = chipSelectLine;
13 | this.Frequency = frequency;
14 | this.Data = data;
15 | this.Response = response;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/SPI/Send/SendSPIData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management.Automation;
3 | using System.Device.Spi;
4 |
5 | [Cmdlet(VerbsCommunications.Send, "SPIData")]
6 | public class SendSPIData : Cmdlet
7 | {
8 | [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Position = 0)]
9 | public byte[] Data { get; set; }
10 |
11 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 1)]
12 | public int BusId { get; set; }
13 |
14 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 2)]
15 | public int ChipSelectLine { get; set; }
16 |
17 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, Position = 3)]
18 | public int Frequency { get; set; }
19 |
20 | [Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
21 | public SwitchParameter Raw { get; set; }
22 |
23 | public SendSPIData()
24 | {
25 | this.BusId = 0;
26 | this.ChipSelectLine = 0;
27 | this.Frequency = 500_000; // 500 KHz default speed
28 | }
29 |
30 | protected override void ProcessRecord()
31 | {
32 | var settings = new SpiConnectionSettings(this.BusId, this.ChipSelectLine);
33 | settings.ClockFrequency = this.Frequency;
34 |
35 | using(var spiDevice = SpiDevice.Create(settings))
36 | {
37 | var response = new byte[this.Data.Length];
38 |
39 | spiDevice.TransferFullDuplex(this.Data, response);
40 |
41 | if (this.Raw)
42 | {
43 | WriteObject(response);
44 | }
45 | else
46 | {
47 | SPIData spiData = new SPIData(this.BusId, this.ChipSelectLine, this.Frequency, this.Data, response);
48 | WriteObject(spiData);
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/gen/Resources.cs:
--------------------------------------------------------------------------------
1 |
2 | //------------------------------------------------------------------------------
3 | //
4 | // This code was generated by a dotnet run from src\ResGen folder.
5 | // To add or remove a member, edit your .resx file then rerun src\ResGen.
6 | //
7 | // Changes to this file may cause incorrect behavior and will be lost if
8 | // the code is regenerated.
9 | //
10 | //------------------------------------------------------------------------------
11 |
12 |
13 | using System;
14 | using System.Reflection;
15 |
16 | ///
17 | /// A strongly-typed resource class, for looking up localized strings, etc.
18 | ///
19 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
20 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
21 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
22 |
23 | internal class Resources {
24 |
25 | private static global::System.Resources.ResourceManager resourceMan;
26 |
27 | private static global::System.Globalization.CultureInfo resourceCulture;
28 |
29 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
30 | internal Resources() {
31 | }
32 |
33 | ///
34 | /// Returns the cached ResourceManager instance used by this class.
35 | ///
36 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
37 | internal static global::System.Resources.ResourceManager ResourceManager {
38 | get {
39 | if (object.ReferenceEquals(resourceMan, null)) {
40 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.PowerShell.IoT.resources.Resources", typeof(Resources).Assembly);
41 | resourceMan = temp;
42 | }
43 | return resourceMan;
44 | }
45 | }
46 |
47 | ///
48 | /// Overrides the current threads CurrentUICulture property for all
49 | /// resource lookups using this strongly typed resource class.
50 | ///
51 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
52 | internal static global::System.Globalization.CultureInfo Culture {
53 | get {
54 | return resourceCulture;
55 | }
56 | set {
57 | resourceCulture = value;
58 | }
59 | }
60 |
61 |
62 | ///
63 | /// Looks up a localized string similar to
64 | /// This cmdlet requires PowerShell to be started with root privileges.
65 | ///
66 | ///
67 | internal static string ErrNeedRootPrivileges {
68 | get {
69 | return ResourceManager.GetString("ErrNeedRootPrivileges", resourceCulture);
70 | }
71 | }
72 |
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.IoT/resources/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | This cmdlet requires PowerShell to be started with root privileges.
122 |
123 |
124 |
--------------------------------------------------------------------------------
/src/ResGen/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Text;
8 | using System.Xml.Linq;
9 |
10 | namespace ConsoleApplication
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | IEnumerable dirs;
17 | string fileFilter;
18 |
19 | if (args.Length == 1)
20 | {
21 | // We are assuming resgen is run with 'dotnet run pathToResxFile.resx'.
22 | fileFilter = Path.GetFileName(args[0]);
23 | string moduleDirectory = Path.GetDirectoryName(Path.GetDirectoryName(args[0]));
24 | dirs = new List() { moduleDirectory };
25 | }
26 | else
27 | {
28 | // We are assuming resgen is run with 'dotnet run'
29 | // so we can use relative path to get a parent directory
30 | // to process all *.resx files in all project subdirectories.
31 | fileFilter = "*.resx";
32 | dirs = Directory.EnumerateDirectories("..");
33 | }
34 |
35 | foreach (string folder in dirs)
36 | {
37 | string moduleName = Path.GetFileName(folder);
38 | string resourcePath = Path.Combine(folder, "resources");
39 |
40 | if (Directory.Exists(resourcePath))
41 | {
42 | string genFolder = Path.Combine(folder, "gen");
43 | if (!Directory.Exists(genFolder))
44 | {
45 | Directory.CreateDirectory(genFolder);
46 | }
47 |
48 | foreach (string resxPath in Directory.EnumerateFiles(resourcePath, fileFilter))
49 | {
50 | string className = Path.GetFileNameWithoutExtension(resxPath);
51 | string sourceCode = GetStronglyTypeCsFileForResx(resxPath, moduleName, className);
52 | string outPath = Path.Combine(genFolder, className + ".cs");
53 | Console.WriteLine("ResGen for " + outPath);
54 | File.WriteAllText(outPath, sourceCode);
55 | }
56 | }
57 | }
58 | }
59 |
60 | private static string GetStronglyTypeCsFileForResx(string xmlPath, string moduleName, string className)
61 | {
62 | // Example
63 | //
64 | // className = Full.Name.Of.The.ClassFoo
65 | // shortClassName = ClassFoo
66 | // namespaceName = Full.Name.Of.The
67 |
68 | string shortClassName = className;
69 | string namespaceName = null;
70 | int lastIndexOfDot = className.LastIndexOf('.');
71 | if (lastIndexOfDot != -1)
72 | {
73 | namespaceName = className.Substring(0, lastIndexOfDot);
74 | shortClassName = className.Substring(lastIndexOfDot + 1);
75 | }
76 |
77 | var entries = new StringBuilder();
78 | XElement root = XElement.Parse(File.ReadAllText(xmlPath));
79 | foreach (var data in root.Elements("data"))
80 | {
81 | string value = data.Value.Replace("\n", "\n ///");
82 | string name = data.Attribute("name").Value.Replace(' ', '_');
83 | entries.AppendFormat(ENTRY, name, value);
84 | }
85 |
86 | string bodyCode = string.Format(BODY, shortClassName, moduleName, entries.ToString(), className);
87 | if (namespaceName != null)
88 | {
89 | bodyCode = string.Format(NAMESPACE, namespaceName, bodyCode);
90 | }
91 |
92 | string resultCode = string.Format(BANNER, bodyCode).Replace("\r\n?|\n", "\r\n");
93 | return resultCode;
94 | }
95 |
96 | private static readonly string BANNER = @"
97 | //------------------------------------------------------------------------------
98 | //
99 | // This code was generated by a dotnet run from src\ResGen folder.
100 | // To add or remove a member, edit your .resx file then rerun src\ResGen.
101 | //
102 | // Changes to this file may cause incorrect behavior and will be lost if
103 | // the code is regenerated.
104 | //
105 | //------------------------------------------------------------------------------
106 |
107 | {0}
108 | ";
109 |
110 | private static readonly string NAMESPACE = @"
111 | namespace {0} {{
112 | {1}
113 | }}
114 | ";
115 | private static readonly string BODY = @"
116 | using System;
117 | using System.Reflection;
118 |
119 | ///
120 | /// A strongly-typed resource class, for looking up localized strings, etc.
121 | ///
122 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")]
123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
124 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
125 |
126 | internal class {0} {{
127 |
128 | private static global::System.Resources.ResourceManager resourceMan;
129 |
130 | private static global::System.Globalization.CultureInfo resourceCulture;
131 |
132 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(""Microsoft.Performance"", ""CA1811:AvoidUncalledPrivateCode"")]
133 | internal {0}() {{
134 | }}
135 |
136 | ///
137 | /// Returns the cached ResourceManager instance used by this class.
138 | ///
139 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
140 | internal static global::System.Resources.ResourceManager ResourceManager {{
141 | get {{
142 | if (object.ReferenceEquals(resourceMan, null)) {{
143 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(""{1}.resources.{3}"", typeof({0}).Assembly);
144 | resourceMan = temp;
145 | }}
146 | return resourceMan;
147 | }}
148 | }}
149 |
150 | ///
151 | /// Overrides the current threads CurrentUICulture property for all
152 | /// resource lookups using this strongly typed resource class.
153 | ///
154 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
155 | internal static global::System.Globalization.CultureInfo Culture {{
156 | get {{
157 | return resourceCulture;
158 | }}
159 | set {{
160 | resourceCulture = value;
161 | }}
162 | }}
163 | {2}
164 | }}
165 | ";
166 |
167 | private static readonly string ENTRY = @"
168 |
169 | ///
170 | /// Looks up a localized string similar to {1}
171 | ///
172 | internal static string {0} {{
173 | get {{
174 | return ResourceManager.GetString(""{0}"", resourceCulture);
175 | }}
176 | }}
177 | ";
178 |
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/ResGen/README.md:
--------------------------------------------------------------------------------
1 | ResGen was copied from [PowerShell/PowerShell](https://github.com/PowerShell/PowerShell/tree/master/src/ResGen).
2 |
3 | In this case ResGen is used to process resource file `src\Microsoft.PowerShell.IoT\resources\Resources.resx`
4 | and to generate `src\Microsoft.PowerShell.IoT\gen\Resources.cs` that is used in the build.
5 |
6 | For any modification to resources:
7 |
8 | 1. make required changes in Resources.resx using a text editor
9 | 1. generate updated Resources.cs:
10 | 1. `cd src\ResGen`
11 | 1. `dotnet run`
12 | 1. compile IoT module as usual to ensure there are no build breaks
13 | 1. check in updated `Resources.resx` and `Resources.cs`
14 |
15 | [More info on ResGen](https://github.com/PowerShell/PowerShell/blob/master/docs/dev-process/resx-files.md).
16 |
--------------------------------------------------------------------------------
/src/ResGen/ResGen.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Generates C# typed bindings for .resx files
5 | netcoreapp2.0
6 | resgen
7 | Exe
8 | win7-x86;win7-x64;osx.10.12-x64;linux-x64
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/psiot.Tests.ps1:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT License.
3 |
4 | Describe "PowerShell IoT tests" {
5 | BeforeAll {
6 | # This creates the session to the test Pi. The hostname maps to a random IP
7 | $Global:SESSION = New-PSSession -HostName raspberry -UserName pi
8 | }
9 | Context "I2C tests" {
10 | BeforeAll {
11 | Invoke-Command -Session $Global:SESSION -ScriptBlock {
12 | # Import the example BME280 which wraps PowerShell IoT cmdlets
13 | Import-Module Microsoft.PowerShell.IoT.BME280
14 | }
15 |
16 | }
17 | It "Can get the the BME280 I2C device" {
18 | $device = Invoke-Command -Session $Global:SESSION -ScriptBlock {
19 | return Get-BME280Device -Id 0x76
20 | }
21 | $device | Should -Not -BeNullOrEmpty
22 | $device.Id | Should -Be 118
23 | $device.FriendlyName | Should -Be "BME280"
24 | }
25 | It "Can get the BME280 data" {
26 | $data = Invoke-Command -Session $Global:SESSION -ScriptBlock {
27 | return Get-BME280Data
28 | }
29 | $data.Temperature | Should -Not -BeNullOrEmpty
30 | $data.Pressure | Should -Not -BeNullOrEmpty
31 | $data.Humidity | Should -Not -BeNullOrEmpty
32 | }
33 | }
34 | Context "GPIO tests" {
35 | # GPIO pins can either act as an input or output pin. In other words,
36 | # you can either set a pin's value or read a pin's value. For example,
37 | # if you set pin 20 to "High" (aka 1) and attempt to read the value of
38 | # pin 20, you will not get the result of your previous set operation.
39 |
40 | # To get around this limitation, on the test Raspberry Pi we have two pins
41 | # (22 and 26) connected. By doing this, we can set the value on pin 22 and
42 | # read that value on pin 26. This next test demonstrates that.
43 | It "Can get and set a GPIO's pin value" {
44 | $highValueResult = Invoke-Command -Session $Global:SESSION -ScriptBlock {
45 | Set-GpioPin -Id 26 -Value High
46 | return Get-GpioPin -Id 22
47 | }
48 | $highValueResult.Id | Should -Be 22
49 | $highValueResult.Value | Should -Be "High"
50 |
51 | $lowValueResult = Invoke-Command -Session $Global:SESSION -ScriptBlock {
52 | Set-GpioPin -Id 26 -Value Low
53 | return Get-GpioPin -Id 22
54 | }
55 | $lowValueResult.Id | Should -Be 22
56 | $lowValueResult.Value | Should -Be "Low"
57 | }
58 | It "Can use the -Raw flag to get the raw value" {
59 | $rawValue = Invoke-Command -Session $Global:SESSION -ScriptBlock {
60 | Set-GpioPin -Id 26 -Value High
61 | return Get-GpioPin -Id 22 -Raw
62 | }
63 | $rawValue | Should -Be 1
64 | }
65 | It "Read non-connected pin with PullDown and return Low" {
66 | $result = Invoke-Command -Session $Global:SESSION -ScriptBlock {
67 | return Get-GpioPin -Id 23 -PullMode PullDown -Raw
68 | }
69 | $result | Should -Be 0
70 | }
71 | It "Read non-connected pin with PullUp and return High" {
72 | $result = Invoke-Command -Session $Global:SESSION -ScriptBlock {
73 | return Get-GpioPin -Id 23 -PullMode PullUp -Raw
74 | }
75 | $result | Should -Be 1
76 | }
77 | }
78 | Context "SPI tests" {
79 | # SPI test: LIS3DH motion sensor; datasheet: www.st.com/resource/en/datasheet/lis3dh.pdf
80 | # Read "WHO_AM_I (0Fh)" register; value should be 0x33
81 | It "Can read data from the LIS3DH motion sensor" {
82 | $result = Invoke-Command -Session $Global:SESSION -ScriptBlock {
83 | $d = @(0x8F,0x0)
84 | return Send-SPIData -Channel 0 -Data $d
85 | }
86 | $result.Channel | Should -Be 0
87 | $result.Data[0] | Should -Be 0x8F
88 | $result.Response[1] | Should -Be 0x33
89 | $result.Frequency | Should -Be 500000
90 | }
91 | It "Can use the -Raw flag to get the raw value" {
92 | $result = Invoke-Command -Session $Global:SESSION -ScriptBlock {
93 | $d = @(0x8F,0x0)
94 | return Send-SPIData -Channel 0 -Data $d -Raw
95 | }
96 | $result[1] | Should -Be 0x33
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/tools/vsts.ps1:
--------------------------------------------------------------------------------
1 | Push-Location "$PSScriptRoot/../"
2 |
3 | Install-Module InvokeBuild -Scope CurrentUser -Force
4 |
5 | # Build and package for Pi
6 | Invoke-Build
7 |
8 | # Move build to Pi
9 | ./Move-PSIoTBuild.ps1 -Ip raspberry -WithExample Microsoft.PowerShell.IoT.BME280
10 |
11 | # Run Pester tests
12 | Push-Location "test"
13 | Invoke-Build Test
14 |
15 | Pop-Location
16 | Pop-Location
17 |
--------------------------------------------------------------------------------
/tools/vstsBuild.psm1:
--------------------------------------------------------------------------------
1 | # VSTS task states: Succeeded|SucceededWithIssues|Failed|Cancelled|Skipped
2 | $succeededStateName = 'Succeeded'
3 | $warningStateName = 'SucceededWithIssues'
4 | $errorStateName = 'Failed'
5 |
6 | # store the current state used by *-VstsTaskState and Write-VstsMessage
7 | $script:taskstate = $succeededStateName
8 |
9 | function Clear-VstsTaskState
10 | {
11 | $script:taskstate = $succeededStateName
12 | }
13 |
14 | function Get-TempFolder
15 | {
16 | $tempPath = [System.IO.Path]::GetTempPath()
17 | # Use the agent temp on VSTS which is cleanup between builds (the user temp is not)
18 | if($env:AGENT_TEMPDIRECTORY)
19 | {
20 | $tempPath = $env:AGENT_TEMPDIRECTORY
21 | }
22 |
23 | $tempFolder = Join-Path -Path $tempPath -ChildPath ([System.IO.Path]::GetRandomFileName())
24 | if(!(test-path $tempFolder))
25 | {
26 | $null = New-Item -Path $tempFolder -ItemType Directory
27 | }
28 |
29 | return $tempFolder
30 | }
31 |
32 | $script:AlternateStagingDirectory = $null
33 | function Get-StagingDirectory
34 | {
35 | # environment variable are documented here:
36 | # https://docs.microsoft.com/en-us/vsts/build-release/concepts/definitions/build/variables?tabs=batch
37 | if($env:BUILD_STAGINGDIRECTORY)
38 | {
39 | return $env:BUILD_STAGINGDIRECTORY
40 | }
41 | else {
42 | if(!$script:AlternateStagingDirectory)
43 | {
44 | Write-VstsInformation "Cannot find staging directory, logging environment"
45 | Get-ChildItem env: | ForEach-Object { Write-VstsInformation -message $_}
46 | $script:AlternateStagingDirectory = Get-TempFolder
47 | }
48 | return $script:AlternateStagingDirectory
49 | }
50 | }
51 |
52 | $script:publishedFiles = @()
53 | # Publishes build artifacts
54 | function Publish-VstsBuildArtifact
55 | {
56 | param(
57 | [parameter(Mandatory,HelpMessage="Path to publish artifacts from.")]
58 | [string]$ArtifactPath,
59 | [parameter(HelpMessage="The folder to same artifacts to.")]
60 | [string]$Bucket = 'release',
61 | [parameter(HelpMessage="If an artifact is unzipped, set a variable to the destination path with this name. Only supported with '-ExpectedCount 1'")]
62 | [string]$Variable,
63 | [parameter(HelpMessage="Expected Artifact Count. Will throw if the count does not match. Not specified or -1 will ignore this parameter.")]
64 | [int]$ExpectedCount = -1
65 | )
66 | $ErrorActionPreference = 'Continue'
67 | Write-VstsInformation -message "Publishing artifacts: $ArtifactPath"
68 |
69 | # In VSTS, publish artifacts appropriately
70 | $files = Get-Item -Path $ArtifactPath | Select-Object -ExpandProperty FullName
71 | $destinationPath = Join-Path (Get-StagingDirectory) -ChildPath $Bucket
72 | if(-not (Test-Path $destinationPath))
73 | {
74 | $null = New-Item -Path $destinationPath -ItemType Directory
75 | }
76 |
77 | foreach($fileName in $files)
78 | {
79 | # Only publish files once
80 | if($script:publishedFiles -inotcontains $fileName)
81 | {
82 | $leafFileName = $(Split-path -Path $fileName -Leaf)
83 |
84 | $extension = [System.IO.Path]::GetExtension($leafFileName)
85 | $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($leafFileName)
86 | # Only expand the symbol '.zip' package
87 | if($extension -ieq '.zip' -and $nameWithoutExtension.Contains("symbols"))
88 | {
89 | $unzipPath = (Join-Path $destinationPath -ChildPath $nameWithoutExtension)
90 | if($Variable)
91 | {
92 | Write-VstsInformation -message "Setting VSTS variable '$Variable' to '$unzipPath'"
93 | # Sets a VSTS variable for use in future build steps.
94 | Write-Host "##vso[task.setvariable variable=$Variable]$unzipPath"
95 | # Set a variable in the current process. PowerShell will not pickup the variable until the process is restarted otherwise.
96 | Set-Item env:\$Variable -Value $unzipPath
97 | }
98 | Expand-Archive -Path $fileName -DestinationPath $unzipPath
99 | }
100 |
101 | Write-Host "##vso[artifact.upload containerfolder=$Bucket;artifactname=$Bucket]$fileName"
102 | $script:publishedFiles += $fileName
103 | }
104 | }
105 |
106 | if($ExpectedCount -ne -1 -and $files.Count -ne $ExpectedCount)
107 | {
108 | throw "Build did not produce the expected number of binaries. $($files.count) were produced instead of $ExpectedCount."
109 | }
110 | }
111 |
112 | function Write-VstsError {
113 | param(
114 | [Parameter(Mandatory=$true)]
115 | [Object]
116 | $Error,
117 | [ValidateSet("error","warning")]
118 | $Type = 'error'
119 | )
120 |
121 | $message = [string]::Empty
122 | $errorType = $Error.GetType().FullName
123 | $newLine = [System.Environment]::NewLine
124 | switch($errorType)
125 | {
126 | 'System.Management.Automation.ErrorRecord'{
127 | $message = "{0}{2}`t{1}" -f $Error,$Error.ScriptStackTrace,$newLine
128 | }
129 | 'System.Management.Automation.ParseException'{
130 | $message = "{0}{2}`t{1}" -f $Error,$Error.StackTrace,$newLine
131 | }
132 | 'System.Management.Automation.Runspaces.RemotingErrorRecord'
133 | {
134 | $message = "{0}{2}`t{1}{2}`tOrigin: {2}" -f $Error,$Error.ScriptStackTrace,$Error.OriginInfo,$newLine
135 | }
136 | default
137 | {
138 | # Log any unknown error types we get so we can improve logging.
139 | log "errorType: $errorType"
140 | $message = $Error.ToString()
141 | }
142 | }
143 | $message.Split($newLine) | ForEach-Object {
144 | Write-VstsMessage -type $Type -message $PSItem
145 | }
146 | }
147 |
148 | # Log messages which potentially change job status
149 | function Write-VstsMessage {
150 | param(
151 | [ValidateSet("error","warning")]
152 | $type = 'error',
153 | [String]
154 | $message
155 | )
156 |
157 | if($script:taskstate -ne $errorStateName -and $type -eq 'error')
158 | {
159 | $script:taskstate = $errorStateName
160 | }
161 | elseif($script:taskstate -eq $succeededStateName) {
162 | $script:taskstate = $warningStateName
163 | }
164 |
165 | # See VSTS documentation at https://github.com/Microsoft/vsts-tasks/blob/master/docs/authoring/commands.md
166 | # Log task message
167 | Write-Host "##vso[task.logissue type=$type]$message"
168 | }
169 |
170 | # Log informational messages
171 | function Write-VstsInformation {
172 | param(
173 | [String]
174 | $message
175 | )
176 |
177 | Write-Host $message
178 | }
179 |
180 | function Write-VstsTaskState
181 | {
182 | # See VSTS documentation at https://github.com/Microsoft/vsts-tasks/blob/master/docs/authoring/commands.md
183 | # Log task state
184 | Write-Host "##vso[task.complete result=$script:taskstate;]DONE"
185 | }
186 |
187 | Export-ModuleMember @(
188 | 'Publish-VstsBuildArtifact'
189 | 'Write-VstsError'
190 | 'Write-VstsMessage'
191 | 'Clear-VstsTaskState'
192 | 'Write-VstsTaskState'
193 | )
--------------------------------------------------------------------------------
/vsts.yml:
--------------------------------------------------------------------------------
1 | resources:
2 | - repo: self
3 | queue:
4 | name: PowerShell IoT
5 | demands: DotNetFramework
6 | steps:
7 | - task: PowerShell@1
8 | displayName: Run Build
9 | inputs:
10 | scriptType: inlineScript
11 | inlineScript: pwsh -c ./tools/vsts.ps1
12 | - task: PublishTestResults@2
13 | displayName: Publish Test Results
14 | inputs:
15 | testRunner: NUnit
16 | testResultsFiles: '**\Test*.xml'
--------------------------------------------------------------------------------