├── .gitattributes
├── .github
└── workflows
│ ├── docs.yml
│ └── release.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── TPLinkSmartDevices.sln
├── docs
├── docs
│ ├── about.md
│ ├── assets
│ │ └── icon.png
│ ├── docs
│ │ ├── data
│ │ │ ├── hsv.md
│ │ │ ├── light-details.md
│ │ │ └── power.md
│ │ ├── devices
│ │ │ ├── bulb.md
│ │ │ ├── device.md
│ │ │ ├── dimmer.md
│ │ │ ├── multi-plug.md
│ │ │ ├── plug.md
│ │ │ └── smartmeter-plug.md
│ │ ├── discovery.md
│ │ └── index.md
│ ├── getting-started.md
│ ├── index.md
│ ├── schedule.md
│ └── timer.md
├── mkdocs.yml
└── site
│ ├── 404.html
│ ├── about
│ └── index.html
│ ├── assets
│ ├── icon.png
│ ├── images
│ │ └── favicon.png
│ ├── javascripts
│ │ ├── bundle.f9edbbd5.min.js
│ │ ├── bundle.f9edbbd5.min.js.map
│ │ ├── lunr
│ │ │ ├── min
│ │ │ │ ├── lunr.ar.min.js
│ │ │ │ ├── lunr.da.min.js
│ │ │ │ ├── lunr.de.min.js
│ │ │ │ ├── lunr.du.min.js
│ │ │ │ ├── lunr.es.min.js
│ │ │ │ ├── lunr.fi.min.js
│ │ │ │ ├── lunr.fr.min.js
│ │ │ │ ├── lunr.hu.min.js
│ │ │ │ ├── lunr.it.min.js
│ │ │ │ ├── lunr.ja.min.js
│ │ │ │ ├── lunr.jp.min.js
│ │ │ │ ├── lunr.multi.min.js
│ │ │ │ ├── lunr.nl.min.js
│ │ │ │ ├── lunr.no.min.js
│ │ │ │ ├── lunr.pt.min.js
│ │ │ │ ├── lunr.ro.min.js
│ │ │ │ ├── lunr.ru.min.js
│ │ │ │ ├── lunr.stemmer.support.min.js
│ │ │ │ ├── lunr.sv.min.js
│ │ │ │ ├── lunr.tr.min.js
│ │ │ │ └── lunr.vi.min.js
│ │ │ └── tinyseg.min.js
│ │ ├── vendor.c3dc8c49.min.js
│ │ ├── vendor.c3dc8c49.min.js.map
│ │ └── worker
│ │ │ ├── search.8e2cddea.min.js
│ │ │ └── search.8e2cddea.min.js.map
│ └── stylesheets
│ │ ├── main.947af8d5.min.css
│ │ ├── main.947af8d5.min.css.map
│ │ ├── palette.7f672a1f.min.css
│ │ └── palette.7f672a1f.min.css.map
│ ├── docs
│ ├── data
│ │ ├── hsv
│ │ │ └── index.html
│ │ ├── light-details
│ │ │ └── index.html
│ │ └── power
│ │ │ └── index.html
│ ├── devices
│ │ ├── bulb
│ │ │ └── index.html
│ │ ├── device
│ │ │ └── index.html
│ │ ├── multi-plug
│ │ │ └── index.html
│ │ ├── plug
│ │ │ └── index.html
│ │ └── smartmeter-plug
│ │ │ └── index.html
│ ├── discovery
│ │ └── index.html
│ └── index.html
│ ├── getting-started
│ └── index.html
│ ├── index.html
│ ├── search
│ └── search_index.json
│ ├── sitemap.xml
│ └── sitemap.xml.gz
└── tplink-smartdevices
├── Data
├── BoolConverter.cs
├── BulbHSV.cs
├── CountDownRule
│ ├── CountDownRule.cs
│ └── ICountDown.cs
├── DimmerOptions.cs
├── LightDetails.cs
├── PowerData.cs
└── Schedule
│ ├── ISchedule.cs
│ ├── Schedule.cs
│ ├── TimeOption.cs
│ └── Weekdays.cs
├── Devices
├── TPLinkSmartBulb.cs
├── TPLinkSmartDevice.cs
├── TPLinkSmartDimmer.cs
├── TPLinkSmartMeterPlug.cs
├── TPLinkSmartMultiPlug.cs
└── TPLinkSmartPlug.cs
├── Events
└── DeviceFoundEventArgs.cs
├── Messaging
├── IMessageCache.cs
├── ManualMessageCache.cs
├── NoMessageCache.cs
├── SmartHomeProtocolEncoder.cs
├── SmartHomeProtocolMessage.cs
└── TimeGatedMessageCache.cs
├── TPLinkDiscovery.cs
└── TPLinkSmartDevices.csproj
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Publish docs on GitHub Pages
2 | on:
3 | push:
4 | branches:
5 | - master
6 |
7 | jobs:
8 | build:
9 | name: Deploy docs
10 | runs-on: windows-latest
11 | steps:
12 | - name: Checkout master
13 | uses: actions/checkout@v1
14 |
15 | - name: build
16 | working-directory: docs
17 | run: |
18 | pip install mkdocs
19 | pip install mkdocs-material
20 | mkdocs build
21 |
22 | - name: deploy
23 | uses: peaceiris/actions-gh-pages@v3
24 | with:
25 | github_token: ${{ secrets.GITHUB_TOKEN }}
26 | publish_dir: ./docs/site
27 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | jobs:
9 | build:
10 | runs-on: windows-latest
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v2
14 |
15 | - name: Setup .NET
16 | uses: actions/setup-dotnet@v1
17 | with:
18 | dotnet-version: 3.1.x
19 |
20 | - name: Build
21 | run: dotnet build --configuration Release
22 |
23 | - name: Get Version Number
24 | id: get_version_number
25 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
26 | shell: bash
27 |
28 | - name: Pack Assets
29 | id: pack_assets
30 | run: |
31 | Compress-Archive tplink-smartdevices.dll tplink-smartdevices${{ steps.get_version_number.outputs.VERSION }}.zip
32 | working-directory: tplink-smartdevices/bin/Release/netstandard2.0
33 |
34 | - name: Create Release
35 | id: create_release
36 | uses: actions/create-release@v1
37 | env:
38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39 | with:
40 | tag_name: ${{ github.ref }}
41 | release_name: Release ${{ steps.get_version_number.outputs.VERSION }}
42 | body: |
43 | Changes in this Release
44 | - see [Changelog](https://github.com/CodeBardian/tplink-smartdevices-netstandard/blob/master/CHANGELOG.md)
45 | draft: false
46 | prerelease: false
47 |
48 | - name: Upload Release Asset
49 | id: upload-release-asset
50 | uses: actions/upload-release-asset@v1
51 | env:
52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53 | with:
54 | upload_url: ${{ steps.create_release.outputs.upload_url }}
55 | asset_path: tplink-smartdevices/bin/Release/netstandard2.0/tplink-smartdevices${{ steps.get_version_number.outputs.VERSION }}.zip
56 | asset_name: tplink-smartdevices${{ steps.get_version_number.outputs.VERSION }}.zip
57 | asset_content_type: application/zip
58 |
59 | - name: Pack
60 | run: dotnet pack --configuration Release
61 |
62 | - name: Publish Nuget
63 | run: dotnet nuget push "*.nupkg" -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_KEY }}
64 | working-directory: tplink-smartdevices/bin/Release
65 |
66 |
67 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 | solution: TPLinkSmartDevices.sln
3 | mono: latest
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## Changelog
2 |
3 | ### [2.0.1] - 2022-07-29
4 |
5 | #### Added
6 |
7 | - automatic push to nuget on release ([#dafb5be](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commit/dafb5be))
8 |
9 | #### Fixed
10 | - exception on sending commands to multiplugs ([#18](https://github.com/CodeBardian/tplink-smartdevices-netstandard/pull/18))
11 |
12 | ### [2.0.0] - 2021-04-04
13 |
14 | #### Added
15 |
16 | - support for hs220 dimmer switch ([#28556c9](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/28556c9))
17 | - Timers
18 | - Schedules
19 |
20 | #### Changed
21 | - no more `Task.Run` ([#1986900](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/1986900))
22 |
23 | #### Fixed
24 | - exception on retrieving cloud info without internet connection([#96be351e](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/6be351e))
25 |
26 | ### [1.0.4] - 2020-11-16
27 |
28 | #### Added
29 |
30 | - light details of smart bulbs ([#af850dd](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/af850dd))
31 | - apply the four preset light states of smart bulbs ([#03e83c9](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/03e83c9) + [#e68bed7](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/e68bed7))
32 | - transition time between light states for smart bulbs ([#db66403](https://github.com/CodeBardian/tplink-smartdevices-netstandard/commits/db66403))
33 | - support for multi-outlet plugs (HS300, HS107, KP303?)
34 | - ConfigureAwait(false) on awaiting tasks ([#16](https://github.com/CodeBardian/tplink-smartdevices-netstandard/pull/16))
35 |
36 | #### Changed
37 | - avoid blocking in async methods ([#16](https://github.com/CodeBardian/tplink-smartdevices-netstandard/pull/16))
38 | - discovery now accepts broadcast address parameter ([#15](https://github.com/CodeBardian/tplink-smartdevices-netstandard/pull/15))
39 |
40 | #### Fixed
41 | - color changing of kl-130 model ([#9](https://github.com/CodeBardian/tplink-smartdevices-netstandard/pull/16))
42 | - exception on discovering kl-130 model
43 | - exception on energy stat parsing ([#12](https://github.com/CodeBardian/tplink-smartdevices-netstandard/pull/12))
44 |
45 | ### [1.0.3] - 2020-08-08
46 |
47 | #### Added
48 |
49 | - access energy stats of hs110
50 | - handle different hardware versions for hs110
51 |
52 | #### Changed
53 | - project now targets .net standard 2.0
54 | - improved emetering commands with error handling
55 | - improved XML documentation for IntelliSense recommendations
56 |
57 | #### Fixed
58 | - location is no longer of type integer
59 | - udp port correctly closing
60 |
61 | ### [1.0.2] - 2020-04-17
62 |
63 | #### Added
64 |
65 | - associate devices to home network
66 | - configure remote access via tplink cloud and kasa
67 |
68 | #### Changed
69 | - more consistent asynchronous code -> all commands to smart devices are now asynchronous
70 | - restructured parts of code for better readability
71 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tplink-smartdevices-netstandard
2 | .NET Standard 2.0 Library for Discovering and Operating TP-Link Smart Devices
3 | [](https://www.nuget.org/packages/tplink-smartdevices/)
4 | 
5 |
6 | This library allows a developer to discover and operate TP-Link Smart Devices from multiple .NET implementations such as .NET Core, Xamarin, .NET Framework and more.
7 |
8 | This project is migrated to .net standard from Anthony Turner's TP-Link Smart Devices SDK:
9 | https://github.com/anthturner/TPLinkSmartDevices
10 | notable changes include: asynchronous operations, more supported devices, better discovery handling, setup functionality (no need for kasa account and app anymore, except for remote control)
11 |
12 | Consult https://github.com/dotnet/standard/blob/master/docs/versions.md to see which .net platform versions can implement this library!
13 |
14 | #### Supported Devices
15 |
16 | | Type | Supported models | Not tested, maybe working |
17 | | ----------------------- | ---------------------------- |---------------------------------- |
18 | | Plug | HS100, HS110, HS300, HS107 | HS105, HS200, KP200/KP303/KP400 |
19 | | Bulb | KL100/KL110/KL130 | KL50/KL60/LB100/LB110/LB120/LB130 |
20 | | Switch | HS220 | |
21 |
22 | > Doesn't include new protocol for firmware version 1.1.0 on HS100 (Hardware Version 4.1)
23 |
24 | ## Usage
25 | Use NuGet package manager to add a reference to this project, for example with dotnet cli:
26 | ```
27 | > dotnet add package tplink-smartdevices --version 2.0.1
28 | ```
29 |
30 | #### Setup / First Use
31 |
32 | If your devices are already connected to your Wi-Fi network (e.g through TP-Link provided mobile app Kasa) this step can be skipped. Otherwise you can use the following script to associate your smart devices with your home network:
33 |
34 | ```cs
35 | await new TPLinkDiscovery().Associate("ssid", "password");
36 | ```
37 | Note that the device running the program needs to be connected to the network which the tplink devices provide. It should be called "TP-Link_Smart Plug_XXXX" or similar. If you have a brand new plug/bulb this network should automatically appear. Otherwise, hold down the reset button on a plug for about 10 seconds, until its light blinks amber rapidly. For a bulb flip the switch on and off 5 times. Not too quickly though! (About 1 sec per flip).
38 |
39 | ### Discovery
40 |
41 | basic:
42 | ```cs
43 | // Runs in a async Task>
44 | var discoveredDevices = await new TPLinkDiscovery().Discover();
45 | ```
46 |
47 | with event handler:
48 | ```cs
49 | TPLinkDiscovery discovery = new TPLinkDiscovery();
50 | discovery.DeviceFound += delegate {
51 | //Console.WriteLine("Device found: " + e.Device.Alias);
52 | //Log.Debug("DISCOVERY","Device found" + e.Device.Alias);
53 | };
54 | var discoveredDevices = await discovery.Discover();
55 | ```
56 |
57 | ### Power State
58 | ```cs
59 | var smartPlug = await TPLinkSmartPlug.Create("100.10.4.1");
60 | await smartPlug.SetPoweredOn(true); // Turn on relay
61 | await smartPlug.SetPoweredOn(false); // Turn off relay
62 | ```
63 |
64 | or after discovery:
65 | ```cs
66 | foreach (var item in discoveredDevices)
67 | {
68 | if (item is TPLinkSmartPlug plug)
69 | {
70 | await plug.SetPoweredOn(true);
71 | }
72 | else if (item is TPLinkSmartBulb bulb)
73 | {
74 | await bulb.SetPoweredOn(true);
75 | }
76 | }
77 | ```
78 |
79 | ### Timer
80 | ```cs
81 | CountDownRule cdr = new CountDownRule() {
82 | Delay = 3600,
83 | Enabled = true,
84 | PoweredOn = true,
85 | Name = "1h Timer"
86 | }
87 | await plug.AddCountDownRule(cdr);
88 | ```
89 |
90 | ### Schedule
91 | ```cs
92 | Schedule schedule = new Schedule
93 | {
94 | Name = "TurnOffMondays10am",
95 | StartAction = 0,
96 | StartTime = new TimeSpan(10, 0, 0),
97 | StartTimeOption = TimeOption.Custom,
98 | Enabled = true,
99 | Weekdays = Weekdays.Monday,
100 | };
101 | await plug.AddSchedule(schedule);
102 | ```
103 |
104 | ### Remote Control
105 |
106 | If you still want to control your devices remotely (not from within the same network) there is the possibility to link each device independently to your kasa account. It then shows up in your app.
107 | ```cs
108 | smartdevice.ConfigureRemoteAccess("username", "password");
109 | ```
110 | To check if your device is linked to tplink cloud use `RemoteAccessEnabled` property.
111 |
112 | ## Disclaimer
113 | I can not guarantee the functionality of this library as I only tested a HS100 and a KL130 in a Xamarin.Android application yet.
114 |
115 | This library has no affiliation with TP-Link.
116 | TP-Link and all respective product names are copyright TP-Link Technologies Co, Ltd. and/or its subsidiaries and affiliates.
117 |
--------------------------------------------------------------------------------
/TPLinkSmartDevices.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29503.13
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TPLinkSmartDevices", "tplink-smartdevices\TPLinkSmartDevices.csproj", "{2900B1BB-2ED5-455B-89B1-7668C6B77DF0}"
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 | {2900B1BB-2ED5-455B-89B1-7668C6B77DF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {2900B1BB-2ED5-455B-89B1-7668C6B77DF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {2900B1BB-2ED5-455B-89B1-7668C6B77DF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {2900B1BB-2ED5-455B-89B1-7668C6B77DF0}.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 = {BAF6D4C7-56D0-4A2A-86EF-E1E1534BC246}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/docs/docs/about.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeBardian/tplink-smartdevices-netstandard/2566af2a3a184e9746934af5668c5ab9a8735b88/docs/docs/about.md
--------------------------------------------------------------------------------
/docs/docs/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeBardian/tplink-smartdevices-netstandard/2566af2a3a184e9746934af5668c5ab9a8735b88/docs/docs/assets/icon.png
--------------------------------------------------------------------------------
/docs/docs/docs/data/hsv.md:
--------------------------------------------------------------------------------
1 | # BulbHSV Class
2 | Namespace: TPLinkSmartDevices.Data
3 | represents a single color in the HSV color model to change a smart bulbs color
4 |
5 | ## Properties
6 |
7 | ### `Hue`
8 | : Angular dimension representing color, `0°/360°` red, `120°` green, `240°` blue
9 | ``` csharp
10 | public int Hue { get; set; }
11 | ```
12 |
13 | ### `Saturation`
14 | : Resembles various tints of color. Accepts values from 0-100.
15 | ``` csharp
16 | public int Saturation { get; set; }
17 | ```
18 |
19 | ### `Value`
20 | : Brightness of color (mixture of hue with varying amounts of black or white paint). Accepts values from 0-100.
21 | ``` csharp
22 | public int Value { get; set; }
23 | ```
--------------------------------------------------------------------------------
/docs/docs/docs/data/light-details.md:
--------------------------------------------------------------------------------
1 | # LightDetails Class
2 | Namespace: TPLinkSmartDevices.Data
3 | Encapsulates JSON data structure for specific hardware properties of smart bulbs.
4 |
5 | ## Properties
6 |
7 | ### `ColorRenderingIndex`
8 | : Measurement of how true the color of an object looks under the bulb's light. A good CRI for most indoor residential applications is 80 or above
9 | ``` csharp
10 | public int ColorRenderingIndex { get; set; }
11 | ```
12 |
13 | ### `IncandescentEquivalent`
14 | : bulb equals a standard incandescent bulb with this watt value
15 | ``` csharp
16 | public int IncandescentEquivalent { get; set; }
17 | ```
18 |
19 | ### `LampBeamAngle`
20 | : Angle at which the light is distributed or emitted
21 | ``` csharp
22 | public int LampBeamAngle { get; set; }
23 | ```
24 |
25 | ### `MaxLumens`
26 | : maximum brightness of bulb in lumens
27 | ``` csharp
28 | public int MaxLumens { get; set; }
29 | ```
30 |
31 | ### `MaxVoltage`
32 | : maximum operating voltage
33 | ``` csharp
34 | public int MaxVoltage { get; set; }
35 | ```
36 |
37 | ### `MinVoltage`
38 | : minimum operating voltage
39 | ``` csharp
40 | public int MinVoltage { get; set; }
41 | ```
42 |
43 | ### `Wattage`
44 | : energy usage of bulb in watt
45 | ``` csharp
46 | public int Wattage { get; set; }
47 | ```
--------------------------------------------------------------------------------
/docs/docs/docs/data/power.md:
--------------------------------------------------------------------------------
1 | # PowerData Class
2 | Namespace: TPLinkSmartDevices.Data
3 | Encapsulates JSON data structure for current energy use as metered by the HS110 Smart Energy Meter.
4 |
5 | ## Properties
6 |
7 | ### `Voltage`
8 | : Currently measured voltage in volts
9 | ``` csharp
10 | public double Voltage { get; private set; }
11 | ```
12 |
13 | ### `Amperage`
14 | : Currently measured current in amperes
15 | ``` csharp
16 | public double Amperage { get; private set; }
17 | ```
18 |
19 | ### `Power`
20 | : Currently measured power in watts
21 | ``` csharp
22 | public double Power { get; private set; }
23 | ```
24 |
25 | ### `Total`
26 | : Total power consumption in kilowatthours
27 | ``` csharp
28 | public double Total { get; private set; }
29 | ```
--------------------------------------------------------------------------------
/docs/docs/docs/devices/bulb.md:
--------------------------------------------------------------------------------
1 | # TPLinkSmartBulb Class
2 | Namespace: TPLinkSmartDevices.Devices
3 | Inheritance: TPLinkSmartDevice -> TPLinkSmartBulb
4 | encloses bulb specific system information and bulb controls
5 |
6 | ## Properties
7 |
8 | ### `IsColor`
9 | : Returns whether bulb supports color changes
10 | ``` csharp
11 | public bool IsColor { get; private set; }
12 | ```
13 |
14 | ### `IsDimmable`
15 | : Returns whether bulb supports dimming the brightness
16 | ``` csharp
17 | public bool IsDimmable { get; private set; }
18 | ```
19 |
20 | ### `IsVariableColorTemperature`
21 | : Returns whether bulb supports changing of color temperature
22 | ``` csharp
23 | public bool IsVariableColorTemperature { get; private set; }
24 | ```
25 |
26 | ### `Brightness`
27 | : Returns bulb brightness in percent
28 | ``` csharp
29 | public int Brightness { get; private set; }
30 | ```
31 |
32 | ### `ColorTemperature`
33 | : Returns bulbs color temperature in kelvin
34 | ``` csharp
35 | public int ColorTemperature { get; private set; }
36 | ```
37 |
38 | ### `LightDetails`
39 | : Contains further hardware specifications of this bulb, , see [`LightDetails`](/docs/data/light-details.md) reference
40 | ``` csharp
41 | public LightDetails LightDetails { get; private set; }
42 | ```
43 |
44 | ### `HSV`
45 | : Returns bulb color in HSV scheme
46 | ``` csharp
47 | public BulbHSV HSV { get; private set; }
48 | ```
49 |
50 | ### `PoweredOn`
51 | : Returns whether bulb is powered on
52 | ``` csharp
53 | public bool PoweredOn { get; private set; }
54 | ```
55 |
56 | ### `PreferredLightStates`
57 | : Returns collection of the four light state preset configurations
58 | ``` csharp
59 | public List PreferredLightStates { get; }
60 | ```
61 |
62 | ## Constructors
63 |
64 | ### `TPLinkSmartBulb(string, int)`
65 | : Creates a new object of this type, used for KL100/KL110/KL130 bulbs
66 | ``` csharp
67 | public TPLinkSmartBulb(string hostname, int port=9999)
68 | ```
69 |
70 | __Parameters__
71 | : * `#!csharp string hostname`: ip-address of of this bulb
72 | * `#!csharp int port`: bulb communicates on this port, defaults to `9999`
73 |
74 | ## Methods
75 |
76 | ### `Create(string, int)` {: #create }
77 | : Factory instantiation method. Returns a new instance of this type.
78 | ``` csharp
79 | public static async Task Create(string hostname, int port = 9999)
80 | ```
81 |
82 | __Parameters__
83 | : * `#!csharp string hostname`: ip-address of of this bulb
84 | * `#!csharp int port`: bulb communicates on this port, defaults to `9999`
85 |
86 | ### `Refresh()`
87 | : Refreshes all properties of this bulb (includes a call to [`TPLinkSmartDevice.Refresh(dynamic)`](device.md#refreshdynamic) for the common device information)
88 | ``` csharp
89 | public async Task Refresh()
90 | ```
91 |
92 | ### `SetPoweredOn(bool)`
93 | : Change the power state of this bulb
94 | ``` csharp
95 | public async task SetPoweredOn(bool value)
96 | ```
97 |
98 | __Parameters__
99 | : * `#!csharp bool value`: `true` power on, `false` power off
100 |
101 | ### `SetBrightness(int, int)`
102 | : Change the bulbs brightness
103 | ``` csharp
104 | public void SetBrightness(int brightness, int transition_period = 0)
105 | ```
106 |
107 | __Parameters__
108 | : * `#!csharp int brightness`: brightness value in percent
109 | * `#!csharp int transition_period` (optional): time in milliseconds in which the bulb transitions from old to new brightness. Allowed values between `0` and `10000`
110 |
111 | __Exceptions__
112 | : * `#!csharp NotSupportedException`: the bulb does not support dimming
113 | * `#!csharp ArgumentException`: `transition_period` only allows values between `0` and `10000`
114 |
115 | ### `SetColorTemp(int, int)`
116 | : Change the bulbs color temperature
117 | ``` csharp
118 | public void SetColorTemp(int colortemp, int transition_period = 0)
119 | ```
120 |
121 | __Parameters__
122 | : * `#!csharp int colortemp`: color temperature in kelvin, common values ranging between 2700K (soft light) to 6500K (bright daylight)
123 | * `#!csharp int transition_period` (optional): time in milliseconds in which the bulb transitions from old to new brightness. Allowed values between `0` and `10000`
124 |
125 | __Exceptions__
126 | : * `#!csharp NotSupportedException`: the bulb does not support color temperature changes
127 | * `#!csharp ArgumentException`: `transition_period` only allows values between `0` and `10000`
128 |
129 | !!! note
130 | Color temperature values depend on device model, for instance KL120 supports 2500K-5000K and KL130 2700K-9000K!
131 |
132 | ### `SetHSV(BulbHSV, int)` {: #sethsv }
133 | : Change the bulbs color
134 | ``` csharp
135 | public void SetHSV(BulbHSV hsv, int transition_period = 0)
136 | ```
137 |
138 | __Parameters__
139 | : * `#!csharp BulbHSV hsv`: color in HSV color scheme, see [`BulbHSV`](/docs/data/hsv) reference
140 | * `#!csharp int transition_period` (optional): time in milliseconds in which the bulb transitions from old to new brightness. Allowed values between `0` and `10000`
141 |
142 | __Exceptions__
143 | : * `#!csharp NotSupportedException`: the bulb does not support color changes
144 | * `#!csharp ArgumentException`: `transition_period` only allows values between `0` and `10000`
145 |
146 | __Example__
147 | ``` csharp
148 | BulbHSV red = new BulbHSV { Hue = 0, Saturation = 100, Value = 100 }; // red HSV(0, 100, 100)
149 |
150 | smartBulb.SetHSV(red);
151 | ```
152 |
153 | ### `ApplyPreset(int)`
154 | : Operate smart bulb on one of the four light state presets
155 | ``` csharp
156 | public void ApplyPreset(int presetIndex)
157 | ```
158 |
159 | __Parameters__
160 | : * `#!csharp int presetIndex`: index of the four presets, ranging from `0` to `3`
161 |
162 | __Exceptions__
163 | : * `#!csharp ArgumentOutOfRangeException`: `presetIndex` only allows values between `0` and `3`
164 |
--------------------------------------------------------------------------------
/docs/docs/docs/devices/device.md:
--------------------------------------------------------------------------------
1 | # TPLinkSmartDevice Class
2 | Namespace: TPLinkSmartDevices.Devices
3 | provides top-level functionalities which all smart devices use, including set up of remote access and several system information properties
4 |
5 | ## Properties
6 |
7 | ### `Alias`
8 | : Returns the user specified (or default) name of this device
9 | ``` csharp
10 | public string Alias { get; private set; }
11 | ```
12 |
13 | ### `CloudServer`
14 | : Returns the name of the server this device communicates to for cloud commands
15 | ``` csharp
16 | public string CloudServer { get; private set; }
17 | ```
18 |
19 | ### `DeviceId`
20 | : Returns the id of this device
21 | ``` csharp
22 | public string DeviceId { get; private set; }
23 | ```
24 |
25 | ### `DevName`
26 | : Returns the name of this device
27 | ``` csharp
28 | public string DevName { get; private set; }
29 | ```
30 |
31 | ### `FirmwareId`
32 | : Returns the firmware id of this device
33 | ``` csharp
34 | public string FirmwareId { get; private set; }
35 | ```
36 |
37 | ### `HardwareId`
38 | : Returns the hardware id of this device
39 | ``` csharp
40 | public string HardwareId { get; private set; }
41 | ```
42 |
43 | ### `HardwareVersion`
44 | : Returns the hardware version of this device
45 | ``` csharp
46 | public string HardwareVersion { get; private set; }
47 | ```
48 |
49 | ### `Hostname`
50 | : Returns the ip-address of this device
51 | ``` csharp
52 | public string Hostname { get; private set; }
53 | ```
54 |
55 | ### `LocationLatLong`
56 | : Returns the coordinates of the rough position the device is located at (location of network). `LocationLatLong[0]` is latitude, `LocationLatLong[1]` is longitude
57 | ``` csharp
58 | public double[] LocationLatLong { get; private set; }
59 | ```
60 |
61 | !!! caution
62 | whether you find it questionable (I do!) or not, tp-link's devices collect data on position of your network.
63 |
64 |
65 | ### `MacAddress`
66 | : Returns the mac address of this device
67 | ``` csharp
68 | public string MacAddress { get; private set; }
69 | ```
70 |
71 | ### `Model`
72 | : Returns the model and region code (EU,US,UK,JP, ...) of this device
73 | ``` csharp
74 | public string Model { get; private set; }
75 | ```
76 |
77 | ### `OemId`
78 | : Returns the manufacturers id of this device
79 | ``` csharp
80 | public string OemId { get; private set; }
81 | ```
82 |
83 | ### `Port`
84 | : Returns the port this device communicates on
85 | ``` csharp
86 | public int Port { get; private set; }
87 | ```
88 |
89 | ### `RemoteAccessEnabled`
90 | : Returns whether this device is configured for remote access via Kasa app
91 | ``` csharp
92 | public bool RemoteAccessEnabled { get; private set; }
93 | ```
94 |
95 | ### `RSSI`
96 | : Returns signal strength
97 | ``` csharp
98 | public int RSSI { get; private set; }
99 | ```
100 |
101 | ### `Type`
102 | :
103 | ``` csharp
104 | public string Type { get; private set; }
105 | ```
106 |
107 | ## Methods
108 |
109 | ### `ConfigureRemoteAccess(string, string)`
110 | : Binds account with the specified credentials to tp-link's cloud server
111 | ``` csharp
112 | public async Task ConfigureRemoteAccess(string username, string password)
113 | ```
114 |
115 | __Parameters__
116 | : * `#!csharp string username`: username (e-mail address) of kasa account
117 | * `#!csharp string password`: password of kasa account
118 |
119 | ### `UnbindRemoteAccess()`
120 | : Unbinds currently connected account from tp-link's cloud server
121 | ``` csharp
122 | public void UnbindRemoteAccess()
123 | ```
124 |
125 | ### `GetCloudInfo()`
126 | : Refreshes cloud information and sets [`RemoteAccessEnabled`](#remoteaccessenabled) and [`CloudServer`](#cloudserver) properties accordingly
127 | ``` csharp
128 | public void GetCloudInfo()
129 | ```
130 |
131 | ### `GetTime()`
132 | : Returns current internal time of this device
133 | ``` csharp
134 | public DateTime GetTime()
135 | ```
136 |
137 | !!! danger "Needs Maintenance"
138 | This method needs maintenance. It is discouraged using it due to unexpected results or errors occurring
139 |
140 | ### `Refresh(dynamic)`
141 | : Refreshes all properties of this device (includes a call to [`GetCloudInfo()`](#getcloudinfo))
142 | ``` csharp
143 | public async Task Refresh(dynamic sysInfo = null)
144 | ```
145 |
146 | __Parameters__
147 | : * `#!csharp dynamic sysInfo`: response of smart devices on system properties, defaults to `null` which results in a new request being made
148 |
149 | ### `SetAlias(string)`
150 | : Sets alias of this device
151 | ``` csharp
152 | public void SetAlias(string value)
153 | ```
154 |
155 | __Parameters__
156 | : * `#!csharp string value`: new alias to set
157 |
158 |
159 |
--------------------------------------------------------------------------------
/docs/docs/docs/devices/dimmer.md:
--------------------------------------------------------------------------------
1 | # TPLinkSmartDimmmer Class
2 | Namespace: TPLinkSmartDevices.Devices
3 | Inheritance: TPLinkSmartDevice -> TPLinkSmartDimmer
4 | controls for wall switches with dimmer functionality
5 |
6 | ## Properties
7 |
8 | ### `Brightness`
9 | : Returns brightness (dimmer value) in percent
10 | ``` csharp
11 | public int Brightness { get; private set; }
12 | ```
13 |
14 | ### `Options`
15 | : Returns an object of type [`DimmerOptions`]() with configuration properties
16 | ``` csharp
17 | public DimmerOptions Options { get; private set; }
18 | ```
19 |
20 | ### `Presets`
21 | : Returns array of the four dimmer state preset configurations containing brightness values
22 | ``` csharp
23 | public int[] Presets { get; private set; }
24 | ```
25 |
26 | ### `PoweredOn`
27 | : Returns whether switch is powered on
28 | ``` csharp
29 | public bool PoweredOn { get; private set; }
30 | ```
31 |
32 | ## Constructors
33 |
34 | ### `TPLinkSmartPlug(string, int, DimmerOptions)`
35 | : Creates a new object of this type, used for HS220 wall switch
36 | ``` csharp
37 | public TPLinkSmartPlug(string hostname, int port=9999, DimmerOptions opts = null)
38 | ```
39 |
40 | __Parameters__
41 | : * `#!csharp string hostname`: ip-address of this device
42 | * `#!csharp int port`: device communicates on this port, defaults to `9999`
43 | * `#!csharp DimmerOptions opts`: configuration properties`
44 |
45 | ## Methods
46 |
47 | ### `Create(string, int, DimmerOptions)` {: #create }
48 | : Factory instantiation method. Returns a new instance of this type.
49 | ``` csharp
50 | public static async Task Create(string hostname, int port = 9999, DimmerOptions opts = null)
51 | ```
52 |
53 | __Parameters__
54 | : * `#!csharp string hostname`: ip-address of this device
55 | * `#!csharp int port`: device communicates on this port, defaults to `9999`
56 | * `#!csharp DimmerOptions opts`: configuration properties`
57 |
58 | ### `Refresh()`
59 | : Refreshes all properties of this device (includes a call to [`TPLinkSmartDevice.Refresh(dynamic)`](device.md#refreshdynamic) for the common device information)
60 | ``` csharp
61 | public async Task Refresh()
62 | ```
63 |
64 | ### `SetPoweredOn(bool)`
65 | : Change the power state
66 | ``` csharp
67 | public void SetPoweredOn(bool value)
68 | ```
69 |
70 | __Parameters__
71 | : * `#!csharp bool value`: `true` power on, `false` power off
72 |
73 | ### `TransitionBrightness(int, DimmerMode, int)`
74 | : Transition to a specified brightness level
75 | ``` csharp
76 | public async Task TransitionBrightness(int brightness, DimmerMode? mode = null, int? duration = null)
77 | ```
78 |
79 | __Parameters__
80 | : * `#!csharp int brightness`: dimmer brightness value in percent
81 | * `#!csharp DimmerMode mode` (optional): [`DimmerMode`]() to use during this transition, if left empty uses default option from [`Options.Mode`](#options)
82 | * `#!csharp int duration` (optional): time in milliseconds in which the bulb transitions from old to new brightness
83 |
84 | __Exceptions__
85 | : * `#!csharp ArgumentException`: `brightness` should be between `0` and `100`
86 |
87 | ### `SetBrightness(int)`
88 | : Instantly change to a specified brightness level
89 | ``` csharp
90 | public async Task SetBrightness(int brightness)
91 | ```
92 |
93 | __Parameters__
94 | : * `#!csharp int brightness`: dimmer brightness value in percent
95 |
96 | __Exceptions__
97 | : * `#!csharp ArgumentException`: `brightness` should be between `0` and `100`
98 |
99 | ### `SetDoubleClickAction(DimmerMode, int)`
100 | : Configures change mode on double click of switch
101 | ``` csharp
102 | public async Task SetDoubleClickAction(DimmerMode mode, int index=0)
103 | ```
104 |
105 | __Parameters__
106 | : * `#!csharp DimmerMode mode`: [`DimmerMode`]() to use on double clicking the switch
107 | * `#!csharp int index` (optional): zero-based preset index, use in combination with `DimmerMode.Preset` to execute preset on double click
108 |
109 | __Exceptions__
110 | : * `#!csharp ArgumentException`: `index` should be between `0` and `3`
111 |
112 | ### `SetLongPressAction(DimmerMode, int)`
113 | : Configures change mode on long press of switch
114 | ``` csharp
115 | public async Task SetLongPressAction(DimmerMode mode, int index=0)
116 | ```
117 |
118 | __Parameters__
119 | : * `#!csharp DimmerMode mode`: [`DimmerMode`]() to use on long press of switch
120 | * `#!csharp int index` (optional): zero-based preset index, use in combination with `DimmerMode.Preset` to execute preset on long press
121 |
122 | __Exceptions__
123 | : * `#!csharp ArgumentException`: `index` should be between `0` and `3`
124 |
125 | ### `SetFadeOnTime(int)`
126 | : Configures speed of fade on transition
127 | ``` csharp
128 | public async Task SetFadeOnTime(int fadeOnTime)
129 | ```
130 |
131 | __Parameters__
132 | : * `#!csharp int fadeOnTime`: transition time used on next uses of switch when turning on
133 |
134 | __Exceptions__
135 | : * `#!csharp ArgumentException`: `fadeOnTime` should be a positive number
136 |
137 | ### `SetFadeOffTime(int)`
138 | : Configures speed of fade on transition
139 | ``` csharp
140 | public async Task SetFadeOffTime(int fadeOffTime)
141 | ```
142 |
143 | __Parameters__
144 | : * `#!csharp int fadeOffTime`: transition time used on next uses of switch when turning off
145 |
146 | __Exceptions__
147 | : * `#!csharp ArgumentException`: `fadeOffTime` should be a positive number
148 |
--------------------------------------------------------------------------------
/docs/docs/docs/devices/multi-plug.md:
--------------------------------------------------------------------------------
1 | # TPLinkSmartMultiPlug Class
2 | Namespace: TPLinkSmartDevices.Devices
3 | Inheritance: TPLinkSmartDevice -> TPLinkSmartMultiPlug
4 | encloses plug specific system information and controls for plugs with multiple outlets
5 |
6 | ## Properties
7 |
8 | ### `AllOutletsPowered`
9 | : Returns whether all the plugs outlet relais are powered on
10 | ``` csharp
11 | public bool AllOutletsPowered { get; private set; }
12 | ```
13 |
14 | ### `Features`
15 | : Returns the feature (capability) abbreviations for this plug
16 | ``` csharp
17 | public string[] Features { get; private set; }
18 | ```
19 |
20 | ### `LedOn`
21 | : If status led on smart plug is on
22 | ``` csharp
23 | public bool LedOn { get; private set; }
24 | ```
25 |
26 | ### `OutletCount`
27 | : Returns number of outlets on this plug
28 | ``` csharp
29 | public int OutletCount { get; private set; }
30 | ```
31 |
32 | ### `Outlets`
33 | : Returns array of Outlets, containing id's, names and power states of each outlet
34 | ``` csharp
35 | public Outlet[] Outlets { get; private set; }
36 | ```
37 |
38 | ## Constructors
39 |
40 | ### `TPLinkSmartMultiPlug(string, int)`
41 | : Creates a new object of this type, used for HS300/HS107 plug
42 | ``` csharp
43 | public TPLinkSmartPlug(string hostname, int port=9999)
44 | ```
45 |
46 | __Parameters__
47 | : * `#!csharp string hostname`: ip-address of of this plug
48 | * `#!csharp int port`: plug communicates on this port, defaults to `9999`
49 |
50 | ## Methods
51 |
52 | ### `Refresh()`
53 | : Refreshes all properties of this plug (includes a call to [`TPLinkSmartDevice.Refresh(dynamic)`](device.md#refreshdynamic) for the common device information)
54 | ``` csharp
55 | public async Task Refresh()
56 | ```
57 |
58 | ### `SetOutletPowered(bool, int)`
59 | : Change the plugs outlet relay state
60 | ``` csharp
61 | public void SetOutletPowered(bool value, int outledId = -1)
62 | ```
63 |
64 | __Parameters__
65 | : * `#!csharp bool value`: `true` power on, `false` power off
66 | * `#!csharp int outledId`: id of outlet to turn on/off (zero-based index of all outlets)
67 |
68 | __Exceptions__
69 | : * `#!csharp ArgumentException`: plug does not have a outlet with specified `outledId`
70 |
71 | ### `SetLedOn(bool)`
72 | : Change the plugs LED state; branded as night mode by tp-link :)
73 | ``` csharp
74 | public void SetLedOn(bool value)
75 | ```
76 |
77 | __Parameters__
78 | : * `#!csharp bool value`: `true` LED on (day mode), `false` LED off (night mode)
--------------------------------------------------------------------------------
/docs/docs/docs/devices/plug.md:
--------------------------------------------------------------------------------
1 | # TPLinkSmartPlug Class
2 | Namespace: TPLinkSmartDevices.Devices
3 | Inheritance: TPLinkSmartDevice -> TPLinkSmartPlug
4 | encloses plug specific system information and plug controls
5 |
6 | ## Properties
7 |
8 | ### `Features`
9 | : Returns the feature (capability) abbreviations for this plug
10 | ``` csharp
11 | public string[] Features { get; private set; }
12 | ```
13 |
14 | ### `LedOn`
15 | : If status led on smart plug is on
16 | ``` csharp
17 | public bool LedOn { get; private set; }
18 | ```
19 |
20 | ### `OutletPowered`
21 | : Returns whether the plugs outlet relay is powered on
22 | ``` csharp
23 | public bool OutletPowered { get; private set; }
24 | ```
25 |
26 | ### `PoweredOnSince`
27 | : Returns `#!csharp DateTime` the relay was powered on
28 | ``` csharp
29 | public DateTime PoweredOnSince { get; private set; }
30 | ```
31 |
32 | ## Constructors
33 |
34 | ### `TPLinkSmartPlug(string, int)`
35 | : Creates a new object of this type, used for HS100/HS105 plug
36 | ``` csharp
37 | public TPLinkSmartPlug(string hostname, int port=9999)
38 | ```
39 |
40 | __Parameters__
41 | : * `#!csharp string hostname`: ip-address of of this plug
42 | * `#!csharp int port`: plug communicates on this port, defaults to `9999`
43 |
44 | ## Methods
45 |
46 | ### `Create(string, int)` {: #create }
47 | : Factory instantiation method. Returns a new instance of this type.
48 | ``` csharp
49 | public static async Task Create(string hostname, int port = 9999)
50 | ```
51 |
52 | __Parameters__
53 | : * `#!csharp string hostname`: ip-address of of this plug
54 | * `#!csharp int port`: plug communicates on this port, defaults to `9999`
55 |
56 | ### `Refresh()`
57 | : Refreshes all properties of this plug (includes a call to [`TPLinkSmartDevice.Refresh(dynamic)`](device.md#refreshdynamic) for the common device information)
58 | ``` csharp
59 | public async Task Refresh()
60 | ```
61 |
62 | ### `SetPoweredOn(bool)` {: #power }
63 | : Change the plugs outlet relay state
64 | ``` csharp
65 | public async Task SetPoweredOn(bool value)
66 | ```
67 |
68 | __Parameters__
69 | : * `#!csharp bool value`: `true` power on, `false` power off
70 |
71 | ### `SetLedOn(bool)`
72 | : Change the plugs LED state; branded as night mode by tp-link :)
73 | ``` csharp
74 | public void SetLedOn(bool value)
75 | ```
76 |
77 | __Parameters__
78 | : * `#!csharp bool value`: `true` LED on (day mode), `false` LED off (night mode)
--------------------------------------------------------------------------------
/docs/docs/docs/devices/smartmeter-plug.md:
--------------------------------------------------------------------------------
1 | # TPLinkSmartMeterPlug Class
2 | Namespace: TPLinkSmartDevices.Devices
3 | Inheritance: TPLinkSmartPlug -> TPLinkSmartMeterPlug
4 | provides data on power consumption of comsumers connected to a HS110 plug
5 |
6 | ## Properties
7 |
8 | ### `CurrentPowerUsage`
9 | : Returns a [`PowerData`](/docs/data/power) object including power usage data from the latest call to the construtor or [`.Refresh()`](#refresh)
10 | ``` csharp
11 | public PowerData CurrentPowerUsage { get; private set; }
12 | ```
13 |
14 | ### `IGain`
15 | : Returns ratio of output current to input current.
16 | ``` csharp
17 | public uint IGain { get; private set; }
18 | ```
19 |
20 | ### `VGain`
21 | : Returns ratio of output voltage to input voltage.
22 | ``` csharp
23 | public uint VGain { get; private set; }
24 | ```
25 |
26 | ## Constructors
27 |
28 | ### `TPLinkSmartMeterPlug(string)`
29 | : Creates a new object of this type, used for HS110 plug
30 | ``` csharp
31 | public TPLinkSmartMeterPlug(string hostname)
32 | ```
33 |
34 | __Parameters__
35 | : * `#!csharp string hostname`: ip-address of of this plug
36 |
37 | ## Methods
38 |
39 | ### `Create(string, int)` {: #create }
40 | : Factory instantiation method. Returns a new instance of this type.
41 | ``` csharp
42 | public static async Task Create(string hostname, int port = 9999)
43 | ```
44 |
45 | __Parameters__
46 | : * `#!csharp string hostname`: ip-address of of this plug
47 | * `#!csharp int port`: plug communicates on this port, defaults to `9999`
48 |
49 | ### `Refresh()`
50 | : Updates current power usage, gain data and all other properties of this plug (includes a call to [`TPLinkSmartPlug.Refresh()`](plug.md#refresh) for the common device information)
51 | ``` csharp
52 | public async Task Refresh()
53 | ```
54 |
55 | ### `EraseStats()`
56 | : Erases all collected e-meter statistics of this plug
57 | ``` csharp
58 | public void EraseStats()
59 | ```
60 |
61 |
62 | ### `GetMonthStats(DateTime, float)`
63 | : Queries collected usage statistics from a specific month. Returns a `#!csharp Dictionary` of each day in a month and energy consumption of that day in kWh)
64 | ``` csharp
65 | public async Task> GetMonthStats(int month, int year)
66 | ```
67 |
68 | __Parameters__
69 | : * `#!csharp int month`: month of year, ranging from `1`(January) to `12`(December)
70 | * `#!csharp int year`:
71 |
72 | ### `GetYearStats(int, float)`
73 | : Queries collected usage statistics for a whole year. Returns a `#!csharp Dictionary` of each month and energy consumption of that month in kWh)
74 | ``` csharp
75 | public async Task> GetYearStats(int year)
76 | ```
77 |
78 | __Parameters__
79 | : * `#!csharp int year`:
--------------------------------------------------------------------------------
/docs/docs/docs/discovery.md:
--------------------------------------------------------------------------------
1 | # TPLinkDiscovery Class
2 | Namespace: TPLinkSmartDevices
3 | handles discovery of new smart devices and connection of factory new devices to a network
4 |
5 | ## Properties
6 |
7 | ### `DiscoveredDevices`
8 | : Returns a list of [`TPLinkSmartDevice`](devices/device.md)'s from the latest call of [`.Discover()`](discovery.md#discover). This property is read-only.
9 | ``` csharp
10 | public List DiscoveredDevices { get; private set; }
11 | ```
12 |
13 | ## Methods
14 |
15 | ### `Discover(int, int, string)` {: #discover }
16 | : Discovers smart devices within the network of the host via UDP broadcast. Returns a list of [`TPLinkSmartDevice`](devices/device.md)'s.
17 | ``` csharp
18 | public async Task> Discover(int port=9999, int timeout=5000, string target="255.255.255.255")
19 | ```
20 |
21 | __Parameters__
22 | : * `#!csharp int port`: Listen to broadcast responses on this port, defaults to `9999`
23 | * `#!csharp int timeout`: Timespan after which the discovery finishes, defaults to `5000`(5 seconds)
24 | * `#!csharp string target`: ip address of discovery broadcast, defaults to `255.255.255.255`
25 |
26 | !!! tip
27 | The discovery of devices within a network fails under certain circumstances. Some routers seem to block udp packets to the broadcast address (255.255.255.255), which is used to send out a discovery request.
28 | In case of using different subnet's, what seems to resolve the issue is broadcasting to the subnet's local broadcast IP (such as 192.168.0.255, if IP is 192.168.0.X with a subnet mask of 255.255.255.0)
29 |
30 | ### `Associate(string, string, int)`
31 | : Makes smart device connect to specified network credentials
32 | ``` csharp
33 | public async Task Associate(string ssid, string password, int type = 3)
34 | ```
35 |
36 | __Parameters__
37 | : * `#!csharp string ssid`: _Service Set Identifier_ (name) of network to connect to
38 | * `#!csharp string password`: password of network to connect to
39 | * `#!csharp int type`: network protection level, defaults to `3` indicating WPA2
40 |
41 | !!! caution
42 | Host who runs the application needs to be connected to the open configuration network! (TP-Link_Smart Plug_XXXX or similar)
43 |
44 | ## Events
45 |
46 | ### `DeviceFound`
47 | : Triggers when smart device is found during discovery process, granting access to all system properties of that device via the event args
48 | ``` csharp
49 | public event EventHandler DeviceFound;
50 | ```
51 |
52 | __EventArgs__
53 | : * `#!csharp DeviceFoundEventArgs e`
54 |
55 | __Example__
56 | :
57 | ``` csharp
58 | new TPLinkDiscovery().DeviceFound += (s, e) {
59 | ...
60 | Console.WriteLine($"Device found: {e.Device.Alias}");
61 | ...
62 | };
63 | ```
--------------------------------------------------------------------------------
/docs/docs/docs/index.md:
--------------------------------------------------------------------------------
1 | # Full API Reference
2 |
3 | ## Classes
4 |
5 | | TPLinkSmartDevices | Description |
6 | | :---------------------------------| :----------------------------------- |
7 | | [`TPLinkDiscovery`](discovery.md) | handles discovery of new smart devices and connection of factory new devices to a network |
8 |
9 | | TPLinkSmartDevices.Devices | Description |
10 | | :----------------------------------------- | :----------------------------------- |
11 | | [`TPLinkSmartDevice`](devices/device.md) | provides top-level functionalities which all smart devices use, including set up of remote access and several system information properties|
12 | | [`TPLinkSmartPlug`](devices/plug.md) | encloses plug specific system information and plug controls |
13 | | [`TPLinkSmartMeterPlug`](devices/smartmeter-plug.md) | provides data on power consumption of comsumers connected to a HS110 plug |
14 | | [`TPLinkSmartBulb`](devices/bulb.md) | encloses bulb specific system information and bulb controls |
15 | | [`TPLinkSmartMultiPlug`](devices/multi-plug.md) | encloses plug specific system information and controls for plugs with multiple outlets |
16 | | [`TPLinkSmartDimmer`](devices/dimmer.md) | controls for wall switches with dimmer functionality |
17 |
18 | | TPLinkSmartDevices.Data | Description |
19 | | :---------------------------- | :----------------------------------- |
20 | | [`BulbHSV`](data/hsv.md) | represents a single color in the HSV color model to change a smart bulbs color |
21 | | [`PowerData`](data/power.md) | Encapsulates JSON data structure for current energy use as metered by the HS110 Smart Energy Meter |
22 | | [`LightDetails`](data/light-details.md) | Encapsulates JSON data structure for specific hardware properties of smart bulbs |
--------------------------------------------------------------------------------
/docs/docs/getting-started.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ## Installation
4 |
5 | Use NuGet package manager to add a reference to this project
6 |
7 | === ".NET CLI"
8 | ```
9 | > dotnet add package tplink-smartdevices --version 2.0.0
10 | ```
11 | === "PackageReference"
12 | ``` html
13 |
14 | ```
15 | === "Package Manager"
16 | ```
17 | Install-Package tplink-smartdevices -Version 2.0.0
18 | ```
19 |
20 |
21 | !!! note ".NET Standard"
22 | Be aware that this library targets .net standard, which can not be implemented from all of .net platform versions. To see whether the platform you intend to run on is supported take a look [here](https://github.com/dotnet/standard/blob/master/docs/versions.md).
23 |
24 | ## Supported Devices
25 |
26 | | Class | Supported Devices | Not tested, maybe working |
27 | | ----------------------- | ----------------- |---------------------------------- |
28 | | `TPLinkSmartPlug` | HS100 | HS105 |
29 | | `TPLinkSmartMeterPlug` | HS110 | |
30 | | `TPLinkSmartBulb` | KL100/KL110/KL130 | KL50/KL60/LB100/LB110/LB120/LB130 |
31 | | `TPLinkSmartMultiPlug` | HS300/HS107 | KP200/KP303/KP400 |
32 | | `TPLinkSmartDimmer` | HS220 | |
33 |
34 | ## Usage
35 |
36 | ### First Use
37 |
38 | If your devices are already connected to your Wi-Fi network (e.g through TP-Link provided mobile app Kasa) this step can be skipped. Otherwise you can use the following script to associate your smart devices with your home network:
39 |
40 | ``` csharp
41 | await new TPLinkDiscovery().Associate("ssid", "password");
42 | ```
43 |
44 | Full reference for [`TPLinkDiscovery().Associate(string, string)`](docs/discovery.md#associatestring-string-int)
45 |
46 | !!! caution
47 | The device running the above script needs to be connected to the network which the tplink smart devices provide. They should be called "TP-Link_Smart Plug_XXXX" or similar. If you have a brand new plug/bulb this network should automatically appear. Otherwise, hold down the reset button on a plug for about 10 seconds, until its light blinks amber rapidly. For a bulb flip the switch on and off 5 times. Not too quickly though! (About 1 sec per flip).
48 |
49 | ### Discovery
50 |
51 | Smart devices which are already connected to the same network as the host devices (PC, tablet, phone, ...) can be discovered to establish further communcation such as turning the device on/off. The discovery runs in an async `Task>`. There is the possibility to register an event handler which triggers on each discovered device. If the ip-address of smart devices are known and not changing, an object of their associated [classes](#supported-devices) can be created manually without the need for discovery.
52 |
53 | === "Basic"
54 | ``` csharp
55 | var discoveredDevices = await new TPLinkDiscovery().Discover();
56 | ```
57 | Full reference for [`TPLinkDiscovery.Discover()`](docs/discovery.md#discover)
58 | === "With event"
59 | ``` csharp
60 | TPLinkDiscovery discovery = new TPLinkDiscovery();
61 | discovery.DeviceFound += delegate {
62 | ...
63 | Console.WriteLine($"Device found: {e.Device.Alias}");
64 | ...
65 | };
66 | var discoveredDevices = await discovery.Discover();
67 | ```
68 | Full reference for [`TPLinkDiscovery.DeviceFound`](docs/discovery.md#devicefound)
69 | === "Manual instantiation"
70 | ``` csharp
71 | //with constructor (blocking!)
72 | var smartPlug = new TPLinkSmartPlug("100.10.4.1");
73 | //or with async factory method
74 | var smartBulb = await TPLinkSmartPlug.Create("100.10.4.1");
75 | ```
76 | Full reference for [`TPLinkSmartPlug`](docs/devices/plug.md) and [`TPLinkSmartBulb`](docs/devices/bulb.md)
77 |
78 | ### Basic Usage Examples
79 |
80 | Following script is a basic example which describes the use-case of turning on all smart plugs in your current network:
81 |
82 | ``` csharp
83 | var discoveredDevices = await new TPLinkDiscovery().Discover();
84 |
85 | foreach (var item in discoveredDevices)
86 | {
87 | if (item is TPLinkSmartPlug plug)
88 | {
89 | await plug.SetPoweredOn(true);
90 | }
91 | }
92 | ```
93 | Full reference for [`TPLinkSmartPlug.SetPoweredOn(bool)`](docs/devices/plug.md#power)
94 |
95 | Changing color of a single smart bulb (LB130, KL130):
96 |
97 | ``` csharp
98 | var smartBulb = await TPLinkSmartBulb.Create("100.10.4.1");
99 |
100 | BulbHSV red = new BulbHSV { Hue = 0, Saturation = 100, Value = 100 }; // red HSV(0, 100, 100)
101 | BulbHSV yellow = new BulbHSV { Hue = 60, Saturation = 100, Value = 100 }; // yellow HSV(60, 100, 100)
102 |
103 | //apply color (instant)
104 | smartBulb.SetHSV(red);
105 | //apply color with transition time
106 | smartBulb.SetHSV(yellow, 1000);
107 | ```
108 | Full reference for [`TPLinkSmartBulb.SetHSV(BulbHSV, int)`](docs/devices/bulb.md#sethsv)
109 |
110 | ### Remote Control
111 |
112 | If you want to control your devices remotely (not from within the same network) there is the possibility to link each device independently to your kasa account. It then shows up in your Kasa app and can be controlled over the internet from wherever it's needed.
113 |
114 | ``` csharp
115 | smartDevice.ConfigureRemoteAccess("username", "password");
116 | ```
117 | Full reference for [`TPLinkSmartDevice.ConfigureRemoteAccess(string, string)`](docs/devices/device.md#configureremoteaccessstring-string)
118 |
119 | ### Timer
120 |
121 | By setting up a Countdown Rule it is possible to have a device execute a specific action after a certain time runs out. This can for example be used to turn off all devices after half an hour:
122 |
123 | ``` csharp
124 | List cdDevices = discoveredDevices.OfType().ToList();
125 | cdDevices.ForEach(d =>
126 | d.AddCountDownRule(
127 | new CountDownRule() {
128 | Delay = 1800,
129 | Enabled = true,
130 | PoweredOn = false,
131 | Name = "MyTimer"
132 | }
133 | )
134 | );
135 | ```
136 | Full reference for [`CountDownRules`](timer.md)
137 |
138 | ### Schedule
139 | Schedule your smart devices to automatically switch on or off if you are home or away, on sunrise or sunset or whenever you feel like. Example of turning light bulb on each workday at 07:00 in the morning.
140 | ``` csharp
141 | Schedule schedule = new Schedule
142 | {
143 | Name = "MySchedule",
144 | StartAction = 1,
145 | StartTime = new TimeSpan(7, 0, 0),
146 | StartTimeOption = TimeOption.Custom,
147 | Enabled = true,
148 | Weekdays = Weekdays.WorkDays
149 | };
150 | await smartBulb.AddSchedule(schedule);
151 | ```
152 | Full reference for [`Schedule`](schedule.md)
--------------------------------------------------------------------------------
/docs/docs/index.md:
--------------------------------------------------------------------------------
1 | # Welcome to tplink-smartdevices Documentation
2 |
3 | __tplink-smartdevices__ is a .NET standard 2.0 library for discovering and operating TP-Link Smart Devices. It allows a developer to discover and operate TP-Link Smart Devices from multiple .NET implementations such as .NET Core, Xamarin, .NET Framework and more.
4 |
5 | ### Ready to dive in ?
6 |
7 | [Get Started](getting-started.md){: .md-button .md-button--primary }
8 | [Full Documentation](docs/index.md){: .md-button }
9 |
10 |
11 | * [Common Issues](https://www.github.com/CodeBardian/tplink-smartdevices-netstandard)
12 | * [Changelog](https://github.com/CodeBardian/tplink-smartdevices-netstandard/blob/master/CHANGELOG.md)
13 |
14 | ## Supported Devices
15 |
16 | | Class | Supported Devices | Not tested, maybe working |
17 | | ----------------------- | ----------------- |---------------------------------- |
18 | | `TPLinkSmartPlug` | HS100 | HS105, HS200 |
19 | | `TPLinkSmartMeterPlug` | HS110 | |
20 | | `TPLinkSmartBulb` | KL100/KL110/KL130 | KL50/KL60/LB100/LB110/LB120/LB130 |
21 | | `TPLinkSmartMultiPlug` | HS300/HS107 | KP200/KP303/KP400 |
22 | | `TPLinkSmartDimmer` | HS220 | |
23 |
--------------------------------------------------------------------------------
/docs/docs/schedule.md:
--------------------------------------------------------------------------------
1 |
2 | All devices implementing `ISchedule` can perform certain actions repeatedly on a specific time. Use `Schedule` to specify the options. Schedules are executed when the time of day equals `StartTime` as long as
3 | the schedule is `Enabled`. All created schedules can be accessed via the `Schedules` property.
4 |
5 | ``` csharp
6 | Schedule schedule = new Schedule
7 | {
8 | Name = "Test1",
9 | StartAction = 1,
10 | StartTime = new TimeSpan(13, 1, 0),
11 | StartTimeOption = TimeOption.Custom,
12 | Enabled = true,
13 | Weekdays = Weekdays.WeekendDays,
14 | };
15 | await device.AddSchedule(schedule);
16 | ```
17 |
18 | #### Options
19 |
20 | | Property | Type | Description |
21 | | ----------------------- | ----------------- |---------------------------------- |
22 | | `Name` | string | custom name of schedule, shows in kasa app |
23 | | `Enabled` | bool | if the schedule is currently active or not |
24 | | `StartAction` | int | whether to turn device on or off at start of rule. 0 = turn off, 1 = turn on |
25 | | `StartTimeOption` | TimeOption | `TimeOption.Sunset` and `TimeOption.Sunrise` trigger the action at, well, sunset or sunrise. Use `TimeOption.Custom` in conjunction with `StartTime` to set your own timing|
26 | | `StartTime` | TimeSpan | time on which the action triggers when using `StartTimeOption = TimeOption.Custom` e.g. 13:05 would be `TimeSpan(13, 5, 0)` or you can specify in minutes after midnight with `TimeSpan.FromMinutes(785)` |
27 | | `Weekdays` | Weekdays | flag of days on which the schedule is executed. Combine multiple days with bitwise or - operator `Weekdays = Weekdays.Monday | Weekdays.Friday` or use preset combinations like `Weekdays = Weekdays.WeekendDays`|
28 |
29 | some more options are available, they are not well tested as of version 2.0.0
30 |
31 | #### Methods
32 |
33 | ``` csharp
34 | Task ICountDown.RetrieveSchedules();
35 | ```
36 | queries the device for current schedules and updates `Schedules` respectively.
37 |
38 | ---
39 | ``` csharp
40 | Task ICountDown.AddSchedule(Schedule);
41 | ```
42 | adds a new schedule
43 |
44 | ---
45 | ``` csharp
46 | Task ICountDown.EditSchedule(Schedule);
47 | ```
48 | update an existing schedule. Example:
49 | ``` csharp
50 | device.Schedule[0].Weekdays |= Weekdays.Thursday;
51 | await device.EditSchedule(Schedule[0]);
52 | ```
53 |
54 | ---
55 | ``` csharp
56 | Task ICountDown.DeleteSchedule(Schedule);
57 | ```
58 | deletes an existing schedule. Example:
59 | ``` csharp
60 | await device.DeleteSchedule(Schedules[0]);
61 | ```
62 |
63 | ---
64 | ``` csharp
65 | Task ICountDown.Schedules();
66 | ```
67 | deletes all existing schedules.
--------------------------------------------------------------------------------
/docs/docs/timer.md:
--------------------------------------------------------------------------------
1 |
2 | All Devices implementing `ICountDown` can perform certain actions after a timer runs out. Use `CountDownRule` to specify the timer options. All timers only run once, for repeated actions create a [`Schedule`](timer.md).
3 | Currently active timers can be accessed via the `CountDownRules` property.
4 |
5 | ``` csharp
6 | var cdr = new CountDownRule() {
7 | Delay = 1800,
8 | Enabled = true,
9 | PoweredOn = false,
10 | Name = "MyTimer"
11 | }
12 | await device.AddCountDownRule(cdr);
13 | ```
14 |
15 | #### Options
16 |
17 | | Property | Type | Description |
18 | | ----------------------- | ----------------- |---------------------------------- |
19 | | `Name` | string | custom name of timer, shows in kasa app |
20 | | `Enabled` | bool | if the rule is currently active or not |
21 | | `PoweredOn` | bool | if the device should be powered on or off after the timer runs out |
22 | | `Delay` | int | delay in seconds after which the action triggers |
23 |
24 | #### Methods
25 |
26 | ``` csharp
27 | Task ICountDown.RetrieveCountDownRules();
28 | ```
29 | queries the device for current timers and updates `CountDownRules` respectively.
30 |
31 | ---
32 | ``` csharp
33 | Task ICountDown.AddCountDownRule(CountDownRule);
34 | ```
35 | adds a new rule
36 |
37 | ---
38 | ``` csharp
39 | Task ICountDown.EditCountDownRule(CountDownRule);
40 | ```
41 | update an existing rule. Example:
42 | ``` csharp
43 | device.CountDownRules[0].Delay = 36000;
44 | await device.EditCountDownRule(CountDownRules[0]);
45 | ```
46 |
47 | ---
48 | ``` csharp
49 | Task ICountDown.DeleteCountDownRule(CountDownRule);
50 | ```
51 | deletes an existing rule. Example:
52 | ``` csharp
53 | await device.DeleteCountDownRule(CountDownRules[0]);
54 | ```
55 |
56 | ---
57 | ``` csharp
58 | Task ICountDown.DeleteAllCountDownRules();
59 | ```
60 | deletes all existing rules.
--------------------------------------------------------------------------------
/docs/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: tplink-smartdevices-docs
2 | nav:
3 | - Home: 'index.md'
4 | - 'Getting Started': 'getting-started.md'
5 | - Timer: 'timer.md'
6 | - Schedule: 'schedule.md'
7 | - Docs:
8 | - 'TPLinkDiscovery': 'docs/discovery.md'
9 | - Devices:
10 | - 'TPLinkSmartDevice': 'docs/devices/device.md'
11 | - 'TPLinkSmartPlug': 'docs/devices/plug.md'
12 | - 'TPLinkSmartMeterPlug': 'docs/devices/smartmeter-plug.md'
13 | - 'TPLinkSmartBulb': 'docs/devices/bulb.md'
14 | - 'TPLinkSmartMultiPlug': 'docs/devices/multi-plug.md'
15 | - 'TPLinkSmartDimmer': 'docs/devices/dimmer.md'
16 | - Data:
17 | - 'BulbHSV': 'docs/data/hsv.md'
18 | - 'PowerData': 'docs/data/power.md'
19 | - 'LightDetails': 'docs/data/light-details.md'
20 | theme:
21 | name: material
22 | favicon: assets/icon.png
23 | extra:
24 | social:
25 | - icon: fontawesome/brands/github
26 | link: https://github.com/CodeBardian
27 | repo_url: https://www.github.com/CodeBardian/tplink-smartdevices-netstandard
28 | repo_name: CodeBardian/tplink-smartdevices-netstandard
29 | markdown_extensions:
30 | - admonition
31 | - attr_list
32 | - def_list
33 | - pymdownx.tabbed
34 | - pymdownx.superfences
35 | - pymdownx.inlinehilite
36 | - pymdownx.highlight
37 | - pymdownx.snippets
38 | google_analytics:
39 | - UA-145854471-2
40 | - auto
--------------------------------------------------------------------------------
/docs/site/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeBardian/tplink-smartdevices-netstandard/2566af2a3a184e9746934af5668c5ab9a8735b88/docs/site/assets/icon.png
--------------------------------------------------------------------------------
/docs/site/assets/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeBardian/tplink-smartdevices-netstandard/2566af2a3a184e9746934af5668c5ab9a8735b88/docs/site/assets/images/favicon.png
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.da.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Danish` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.de.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `German` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.du.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Dutch` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.fi.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Finnish` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=function(){var e=i.stemmerSupport.Among,r=i.stemmerSupport.SnowballProgram,n=new function(){function i(){f=A.limit,d=f,n()||(f=A.cursor,n()||(d=A.cursor))}function n(){for(var i;;){if(i=A.cursor,A.in_grouping(W,97,246))break;if(A.cursor=i,i>=A.limit)return!0;A.cursor++}for(A.cursor=i;!A.out_grouping(W,97,246);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}function t(){return d<=A.cursor}function s(){var i,e;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(h,10)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.in_grouping_b(x,97,246))return;break;case 2:if(!t())return}A.slice_del()}else A.limit_backward=e}function o(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(v,9))switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"k")||(A.cursor=A.limit-r,A.slice_del());break;case 2:A.slice_del(),A.ket=A.cursor,A.eq_s_b(3,"kse")&&(A.bra=A.cursor,A.slice_from("ksi"));break;case 3:A.slice_del();break;case 4:A.find_among_b(p,6)&&A.slice_del();break;case 5:A.find_among_b(g,6)&&A.slice_del();break;case 6:A.find_among_b(j,2)&&A.slice_del()}else A.limit_backward=e}function l(){return A.find_among_b(q,7)}function a(){return A.eq_s_b(1,"i")&&A.in_grouping_b(L,97,246)}function u(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(C,30)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.eq_s_b(1,"a"))return;break;case 2:case 9:if(!A.eq_s_b(1,"e"))return;break;case 3:if(!A.eq_s_b(1,"i"))return;break;case 4:if(!A.eq_s_b(1,"o"))return;break;case 5:if(!A.eq_s_b(1,"ä"))return;break;case 6:if(!A.eq_s_b(1,"ö"))return;break;case 7:if(r=A.limit-A.cursor,!l()&&(A.cursor=A.limit-r,!A.eq_s_b(2,"ie"))){A.cursor=A.limit-r;break}if(A.cursor=A.limit-r,A.cursor<=A.limit_backward){A.cursor=A.limit-r;break}A.cursor--,A.bra=A.cursor;break;case 8:if(!A.in_grouping_b(W,97,246)||!A.out_grouping_b(W,97,246))return}A.slice_del(),k=!0}else A.limit_backward=e}function c(){var i,e,r;if(A.cursor>=d)if(e=A.limit_backward,A.limit_backward=d,A.ket=A.cursor,i=A.find_among_b(P,14)){if(A.bra=A.cursor,A.limit_backward=e,1==i){if(r=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-r}A.slice_del()}else A.limit_backward=e}function m(){var i;A.cursor>=f&&(i=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.find_among_b(F,2)?(A.bra=A.cursor,A.limit_backward=i,A.slice_del()):A.limit_backward=i)}function w(){var i,e,r,n,t,s;if(A.cursor>=f){if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.eq_s_b(1,"t")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.in_grouping_b(W,97,246)&&(A.cursor=A.limit-r,A.slice_del(),A.limit_backward=e,n=A.limit-A.cursor,A.cursor>=d&&(A.cursor=d,t=A.limit_backward,A.limit_backward=A.cursor,A.cursor=A.limit-n,A.ket=A.cursor,i=A.find_among_b(S,2))))){if(A.bra=A.cursor,A.limit_backward=t,1==i){if(s=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-s}return void A.slice_del()}A.limit_backward=e}}function _(){var i,e,r,n;if(A.cursor>=f){for(i=A.limit_backward,A.limit_backward=f,e=A.limit-A.cursor,l()&&(A.cursor=A.limit-e,A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.in_grouping_b(y,97,228)&&(A.bra=A.cursor,A.out_grouping_b(W,97,246)&&A.slice_del()),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"j")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.eq_s_b(1,"o")?A.slice_del():(A.cursor=A.limit-r,A.eq_s_b(1,"u")&&A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"o")&&(A.bra=A.cursor,A.eq_s_b(1,"j")&&A.slice_del()),A.cursor=A.limit-e,A.limit_backward=i;;){if(n=A.limit-A.cursor,A.out_grouping_b(W,97,246)){A.cursor=A.limit-n;break}if(A.cursor=A.limit-n,A.cursor<=A.limit_backward)return;A.cursor--}A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,b=A.slice_to(),A.eq_v_b(b)&&A.slice_del())}}var k,b,d,f,h=[new e("pa",-1,1),new e("sti",-1,2),new e("kaan",-1,1),new e("han",-1,1),new e("kin",-1,1),new e("hän",-1,1),new e("kään",-1,1),new e("ko",-1,1),new e("pä",-1,1),new e("kö",-1,1)],p=[new e("lla",-1,-1),new e("na",-1,-1),new e("ssa",-1,-1),new e("ta",-1,-1),new e("lta",3,-1),new e("sta",3,-1)],g=[new e("llä",-1,-1),new e("nä",-1,-1),new e("ssä",-1,-1),new e("tä",-1,-1),new e("ltä",3,-1),new e("stä",3,-1)],j=[new e("lle",-1,-1),new e("ine",-1,-1)],v=[new e("nsa",-1,3),new e("mme",-1,3),new e("nne",-1,3),new e("ni",-1,2),new e("si",-1,1),new e("an",-1,4),new e("en",-1,6),new e("än",-1,5),new e("nsä",-1,3)],q=[new e("aa",-1,-1),new e("ee",-1,-1),new e("ii",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1),new e("ää",-1,-1),new e("öö",-1,-1)],C=[new e("a",-1,8),new e("lla",0,-1),new e("na",0,-1),new e("ssa",0,-1),new e("ta",0,-1),new e("lta",4,-1),new e("sta",4,-1),new e("tta",4,9),new e("lle",-1,-1),new e("ine",-1,-1),new e("ksi",-1,-1),new e("n",-1,7),new e("han",11,1),new e("den",11,-1,a),new e("seen",11,-1,l),new e("hen",11,2),new e("tten",11,-1,a),new e("hin",11,3),new e("siin",11,-1,a),new e("hon",11,4),new e("hän",11,5),new e("hön",11,6),new e("ä",-1,8),new e("llä",22,-1),new e("nä",22,-1),new e("ssä",22,-1),new e("tä",22,-1),new e("ltä",26,-1),new e("stä",26,-1),new e("ttä",26,9)],P=[new e("eja",-1,-1),new e("mma",-1,1),new e("imma",1,-1),new e("mpa",-1,1),new e("impa",3,-1),new e("mmi",-1,1),new e("immi",5,-1),new e("mpi",-1,1),new e("impi",7,-1),new e("ejä",-1,-1),new e("mmä",-1,1),new e("immä",10,-1),new e("mpä",-1,1),new e("impä",12,-1)],F=[new e("i",-1,-1),new e("j",-1,-1)],S=[new e("mma",-1,1),new e("imma",0,-1)],y=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],W=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],x=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],A=new r;this.setCurrent=function(i){A.setCurrent(i)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return i(),k=!1,A.limit_backward=e,A.cursor=A.limit,s(),A.cursor=A.limit,o(),A.cursor=A.limit,u(),A.cursor=A.limit,c(),A.cursor=A.limit,k?(m(),A.cursor=A.limit):(A.cursor=A.limit,w(),A.cursor=A.limit),_(),!0}};return function(i){return"function"==typeof i.update?i.update(function(i){return n.setCurrent(i),n.stem(),n.getCurrent()}):(n.setCurrent(i),n.stem(),n.getCurrent())}}(),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.fr.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `French` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,s){return!(!W.eq_s(1,e)||(W.ket=W.cursor,!W.in_grouping(F,97,251)))&&(W.slice_from(r),W.cursor=s,!0)}function i(e,r,s){return!!W.eq_s(1,e)&&(W.ket=W.cursor,W.slice_from(r),W.cursor=s,!0)}function n(){for(var r,s;;){if(r=W.cursor,W.in_grouping(F,97,251)){if(W.bra=W.cursor,s=W.cursor,e("u","U",r))continue;if(W.cursor=s,e("i","I",r))continue;if(W.cursor=s,i("y","Y",r))continue}if(W.cursor=r,W.bra=r,!e("y","Y",r)){if(W.cursor=r,W.eq_s(1,"q")&&(W.bra=W.cursor,i("u","U",r)))continue;if(W.cursor=r,r>=W.limit)return;W.cursor++}}}function t(){for(;!W.in_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}for(;!W.out_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}return!1}function u(){var e=W.cursor;if(q=W.limit,g=q,p=q,W.in_grouping(F,97,251)&&W.in_grouping(F,97,251)&&W.cursor=W.limit){W.cursor=q;break}W.cursor++}while(!W.in_grouping(F,97,251))}q=W.cursor,W.cursor=e,t()||(g=W.cursor,t()||(p=W.cursor))}function o(){for(var e,r;;){if(r=W.cursor,W.bra=r,!(e=W.find_among(h,4)))break;switch(W.ket=W.cursor,e){case 1:W.slice_from("i");break;case 2:W.slice_from("u");break;case 3:W.slice_from("y");break;case 4:if(W.cursor>=W.limit)return;W.cursor++}}}function c(){return q<=W.cursor}function a(){return g<=W.cursor}function l(){return p<=W.cursor}function w(){var e,r;if(W.ket=W.cursor,e=W.find_among_b(C,43)){switch(W.bra=W.cursor,e){case 1:if(!l())return!1;W.slice_del();break;case 2:if(!l())return!1;W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")&&(W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU"));break;case 3:if(!l())return!1;W.slice_from("log");break;case 4:if(!l())return!1;W.slice_from("u");break;case 5:if(!l())return!1;W.slice_from("ent");break;case 6:if(!c())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(z,6))switch(W.bra=W.cursor,e){case 1:l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&W.slice_del()));break;case 2:l()?W.slice_del():a()&&W.slice_from("eux");break;case 3:l()&&W.slice_del();break;case 4:c()&&W.slice_from("i")}break;case 7:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(y,3))switch(W.bra=W.cursor,e){case 1:l()?W.slice_del():W.slice_from("abl");break;case 2:l()?W.slice_del():W.slice_from("iqU");break;case 3:l()&&W.slice_del()}break;case 8:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")))){W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU");break}break;case 9:W.slice_from("eau");break;case 10:if(!a())return!1;W.slice_from("al");break;case 11:if(l())W.slice_del();else{if(!a())return!1;W.slice_from("eux")}break;case 12:if(!a()||!W.out_grouping_b(F,97,251))return!1;W.slice_del();break;case 13:return c()&&W.slice_from("ant"),!1;case 14:return c()&&W.slice_from("ent"),!1;case 15:return r=W.limit-W.cursor,W.in_grouping_b(F,97,251)&&c()&&(W.cursor=W.limit-r,W.slice_del()),!1}return!0}return!1}function f(){var e,r;if(W.cursor=q){if(s=W.limit_backward,W.limit_backward=q,W.ket=W.cursor,e=W.find_among_b(P,7))switch(W.bra=W.cursor,e){case 1:if(l()){if(i=W.limit-W.cursor,!W.eq_s_b(1,"s")&&(W.cursor=W.limit-i,!W.eq_s_b(1,"t")))break;W.slice_del()}break;case 2:W.slice_from("i");break;case 3:W.slice_del();break;case 4:W.eq_s_b(2,"gu")&&W.slice_del()}W.limit_backward=s}}function b(){var e=W.limit-W.cursor;W.find_among_b(U,5)&&(W.cursor=W.limit-e,W.ket=W.cursor,W.cursor>W.limit_backward&&(W.cursor--,W.bra=W.cursor,W.slice_del()))}function d(){for(var e,r=1;W.out_grouping_b(F,97,251);)r--;if(r<=0){if(W.ket=W.cursor,e=W.limit-W.cursor,!W.eq_s_b(1,"é")&&(W.cursor=W.limit-e,!W.eq_s_b(1,"è")))return;W.bra=W.cursor,W.slice_from("e")}}function k(){if(!w()&&(W.cursor=W.limit,!f()&&(W.cursor=W.limit,!m())))return W.cursor=W.limit,void _();W.cursor=W.limit,W.ket=W.cursor,W.eq_s_b(1,"Y")?(W.bra=W.cursor,W.slice_from("i")):(W.cursor=W.limit,W.eq_s_b(1,"ç")&&(W.bra=W.cursor,W.slice_from("c")))}var p,g,q,v=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],h=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],z=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],y=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],C=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],x=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],I=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],P=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],U=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],F=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],S=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],W=new s;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){var e=W.cursor;return n(),W.cursor=e,u(),W.limit_backward=e,W.cursor=W.limit,k(),W.cursor=W.limit,b(),W.cursor=W.limit,d(),W.cursor=W.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.hu.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Hungarian` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,n=L.cursor;if(d=L.limit,L.in_grouping(W,97,252))for(;;){if(e=L.cursor,L.out_grouping(W,97,252))return L.cursor=e,L.find_among(g,8)||(L.cursor=e,e=L.limit)return void(d=e);L.cursor++}if(L.cursor=n,L.out_grouping(W,97,252)){for(;!L.in_grouping(W,97,252);){if(L.cursor>=L.limit)return;L.cursor++}d=L.cursor}}function i(){return d<=L.cursor}function a(){var e;if(L.ket=L.cursor,(e=L.find_among_b(h,2))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e")}}function t(){var e=L.limit-L.cursor;return!!L.find_among_b(p,23)&&(L.cursor=L.limit-e,!0)}function s(){if(L.cursor>L.limit_backward){L.cursor--,L.ket=L.cursor;var e=L.cursor-1;L.limit_backward<=e&&e<=L.limit&&(L.cursor=e,L.bra=e,L.slice_del())}}function c(){var e;if(L.ket=L.cursor,(e=L.find_among_b(_,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function o(){L.ket=L.cursor,L.find_among_b(v,44)&&(L.bra=L.cursor,i()&&(L.slice_del(),a()))}function w(){var e;if(L.ket=L.cursor,(e=L.find_among_b(z,3))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("e");break;case 2:case 3:L.slice_from("a")}}function l(){var e;if(L.ket=L.cursor,(e=L.find_among_b(y,6))&&(L.bra=L.cursor,i()))switch(e){case 1:case 2:L.slice_del();break;case 3:L.slice_from("a");break;case 4:L.slice_from("e")}}function u(){var e;if(L.ket=L.cursor,(e=L.find_among_b(j,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function m(){var e;if(L.ket=L.cursor,(e=L.find_among_b(C,7))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:L.slice_del()}}function k(){var e;if(L.ket=L.cursor,(e=L.find_among_b(P,12))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 9:L.slice_del();break;case 2:case 5:case 8:L.slice_from("e");break;case 3:case 6:L.slice_from("a")}}function f(){var e;if(L.ket=L.cursor,(e=L.find_among_b(F,31))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:L.slice_del();break;case 2:case 5:case 10:case 14:case 19:L.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:L.slice_from("e")}}function b(){var e;if(L.ket=L.cursor,(e=L.find_among_b(S,42))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:L.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:L.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:L.slice_from("e")}}var d,g=[new n("cs",-1,-1),new n("dzs",-1,-1),new n("gy",-1,-1),new n("ly",-1,-1),new n("ny",-1,-1),new n("sz",-1,-1),new n("ty",-1,-1),new n("zs",-1,-1)],h=[new n("á",-1,1),new n("é",-1,2)],p=[new n("bb",-1,-1),new n("cc",-1,-1),new n("dd",-1,-1),new n("ff",-1,-1),new n("gg",-1,-1),new n("jj",-1,-1),new n("kk",-1,-1),new n("ll",-1,-1),new n("mm",-1,-1),new n("nn",-1,-1),new n("pp",-1,-1),new n("rr",-1,-1),new n("ccs",-1,-1),new n("ss",-1,-1),new n("zzs",-1,-1),new n("tt",-1,-1),new n("vv",-1,-1),new n("ggy",-1,-1),new n("lly",-1,-1),new n("nny",-1,-1),new n("tty",-1,-1),new n("ssz",-1,-1),new n("zz",-1,-1)],_=[new n("al",-1,1),new n("el",-1,2)],v=[new n("ba",-1,-1),new n("ra",-1,-1),new n("be",-1,-1),new n("re",-1,-1),new n("ig",-1,-1),new n("nak",-1,-1),new n("nek",-1,-1),new n("val",-1,-1),new n("vel",-1,-1),new n("ul",-1,-1),new n("nál",-1,-1),new n("nél",-1,-1),new n("ból",-1,-1),new n("ról",-1,-1),new n("tól",-1,-1),new n("bõl",-1,-1),new n("rõl",-1,-1),new n("tõl",-1,-1),new n("ül",-1,-1),new n("n",-1,-1),new n("an",19,-1),new n("ban",20,-1),new n("en",19,-1),new n("ben",22,-1),new n("képpen",22,-1),new n("on",19,-1),new n("ön",19,-1),new n("képp",-1,-1),new n("kor",-1,-1),new n("t",-1,-1),new n("at",29,-1),new n("et",29,-1),new n("ként",29,-1),new n("anként",32,-1),new n("enként",32,-1),new n("onként",32,-1),new n("ot",29,-1),new n("ért",29,-1),new n("öt",29,-1),new n("hez",-1,-1),new n("hoz",-1,-1),new n("höz",-1,-1),new n("vá",-1,-1),new n("vé",-1,-1)],z=[new n("án",-1,2),new n("én",-1,1),new n("ánként",-1,3)],y=[new n("stul",-1,2),new n("astul",0,1),new n("ástul",0,3),new n("stül",-1,2),new n("estül",3,1),new n("éstül",3,4)],j=[new n("á",-1,1),new n("é",-1,2)],C=[new n("k",-1,7),new n("ak",0,4),new n("ek",0,6),new n("ok",0,5),new n("ák",0,1),new n("ék",0,2),new n("ök",0,3)],P=[new n("éi",-1,7),new n("áéi",0,6),new n("ééi",0,5),new n("é",-1,9),new n("ké",3,4),new n("aké",4,1),new n("eké",4,1),new n("oké",4,1),new n("áké",4,3),new n("éké",4,2),new n("öké",4,1),new n("éé",3,8)],F=[new n("a",-1,18),new n("ja",0,17),new n("d",-1,16),new n("ad",2,13),new n("ed",2,13),new n("od",2,13),new n("ád",2,14),new n("éd",2,15),new n("öd",2,13),new n("e",-1,18),new n("je",9,17),new n("nk",-1,4),new n("unk",11,1),new n("ánk",11,2),new n("énk",11,3),new n("ünk",11,1),new n("uk",-1,8),new n("juk",16,7),new n("ájuk",17,5),new n("ük",-1,8),new n("jük",19,7),new n("éjük",20,6),new n("m",-1,12),new n("am",22,9),new n("em",22,9),new n("om",22,9),new n("ám",22,10),new n("ém",22,11),new n("o",-1,18),new n("á",-1,19),new n("é",-1,20)],S=[new n("id",-1,10),new n("aid",0,9),new n("jaid",1,6),new n("eid",0,9),new n("jeid",3,6),new n("áid",0,7),new n("éid",0,8),new n("i",-1,15),new n("ai",7,14),new n("jai",8,11),new n("ei",7,14),new n("jei",10,11),new n("ái",7,12),new n("éi",7,13),new n("itek",-1,24),new n("eitek",14,21),new n("jeitek",15,20),new n("éitek",14,23),new n("ik",-1,29),new n("aik",18,26),new n("jaik",19,25),new n("eik",18,26),new n("jeik",21,25),new n("áik",18,27),new n("éik",18,28),new n("ink",-1,20),new n("aink",25,17),new n("jaink",26,16),new n("eink",25,17),new n("jeink",28,16),new n("áink",25,18),new n("éink",25,19),new n("aitok",-1,21),new n("jaitok",32,20),new n("áitok",-1,22),new n("im",-1,5),new n("aim",35,4),new n("jaim",36,1),new n("eim",35,4),new n("jeim",38,1),new n("áim",35,2),new n("éim",35,3)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var n=L.cursor;return e(),L.limit_backward=n,L.cursor=L.limit,c(),L.cursor=L.limit,o(),L.cursor=L.limit,w(),L.cursor=L.limit,l(),L.cursor=L.limit,u(),L.cursor=L.limit,k(),L.cursor=L.limit,f(),L.cursor=L.limit,b(),L.cursor=L.limit,m(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.ja.min.js:
--------------------------------------------------------------------------------
1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.no.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Norwegian` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.pt.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Portuguese` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(k,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("a~");continue;case 2:z.slice_from("o~");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function n(){if(z.out_grouping(y,97,250)){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!0;z.cursor++}return!1}return!0}function i(){if(z.in_grouping(y,97,250))for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return g=z.cursor,!0}function o(){var e,r,s=z.cursor;if(z.in_grouping(y,97,250))if(e=z.cursor,n()){if(z.cursor=e,i())return}else g=z.cursor;if(z.cursor=s,z.out_grouping(y,97,250)){if(r=z.cursor,n()){if(z.cursor=r,!z.in_grouping(y,97,250)||z.cursor>=z.limit)return;z.cursor++}g=z.cursor}}function t(){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return!0}function a(){var e=z.cursor;g=z.limit,b=g,h=g,o(),z.cursor=e,t()&&(b=z.cursor,t()&&(h=z.cursor))}function u(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(q,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("ã");continue;case 2:z.slice_from("õ");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function w(){return g<=z.cursor}function m(){return b<=z.cursor}function c(){return h<=z.cursor}function l(){var e;if(z.ket=z.cursor,!(e=z.find_among_b(F,45)))return!1;switch(z.bra=z.cursor,e){case 1:if(!c())return!1;z.slice_del();break;case 2:if(!c())return!1;z.slice_from("log");break;case 3:if(!c())return!1;z.slice_from("u");break;case 4:if(!c())return!1;z.slice_from("ente");break;case 5:if(!m())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(j,4),e&&(z.bra=z.cursor,c()&&(z.slice_del(),1==e&&(z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del()))));break;case 6:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(C,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 7:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(P,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 8:if(!c())return!1;z.slice_del(),z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del());break;case 9:if(!w()||!z.eq_s_b(1,"e"))return!1;z.slice_from("ir")}return!0}function f(){var e,r;if(z.cursor>=g){if(r=z.limit_backward,z.limit_backward=g,z.ket=z.cursor,e=z.find_among_b(S,120))return z.bra=z.cursor,1==e&&z.slice_del(),z.limit_backward=r,!0;z.limit_backward=r}return!1}function d(){var e;z.ket=z.cursor,(e=z.find_among_b(W,7))&&(z.bra=z.cursor,1==e&&w()&&z.slice_del())}function v(e,r){if(z.eq_s_b(1,e)){z.bra=z.cursor;var s=z.limit-z.cursor;if(z.eq_s_b(1,r))return z.cursor=z.limit-s,w()&&z.slice_del(),!1}return!0}function p(){var e;if(z.ket=z.cursor,e=z.find_among_b(L,4))switch(z.bra=z.cursor,e){case 1:w()&&(z.slice_del(),z.ket=z.cursor,z.limit-z.cursor,v("u","g")&&v("i","c"));break;case 2:z.slice_from("c")}}function _(){if(!l()&&(z.cursor=z.limit,!f()))return z.cursor=z.limit,void d();z.cursor=z.limit,z.ket=z.cursor,z.eq_s_b(1,"i")&&(z.bra=z.cursor,z.eq_s_b(1,"c")&&(z.cursor=z.limit,w()&&z.slice_del()))}var h,b,g,k=[new r("",-1,3),new r("ã",0,1),new r("õ",0,2)],q=[new r("",-1,3),new r("a~",0,1),new r("o~",0,2)],j=[new r("ic",-1,-1),new r("ad",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],C=[new r("ante",-1,1),new r("avel",-1,1),new r("ível",-1,1)],P=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],F=[new r("ica",-1,1),new r("ância",-1,1),new r("ência",-1,4),new r("ira",-1,9),new r("adora",-1,1),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,8),new r("eza",-1,1),new r("logía",-1,2),new r("idade",-1,7),new r("ante",-1,1),new r("mente",-1,6),new r("amente",12,5),new r("ável",-1,1),new r("ível",-1,1),new r("ución",-1,3),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,1),new r("imento",-1,1),new r("ivo",-1,8),new r("aça~o",-1,1),new r("ador",-1,1),new r("icas",-1,1),new r("ências",-1,4),new r("iras",-1,9),new r("adoras",-1,1),new r("osas",-1,1),new r("istas",-1,1),new r("ivas",-1,8),new r("ezas",-1,1),new r("logías",-1,2),new r("idades",-1,7),new r("uciones",-1,3),new r("adores",-1,1),new r("antes",-1,1),new r("aço~es",-1,1),new r("icos",-1,1),new r("ismos",-1,1),new r("osos",-1,1),new r("amentos",-1,1),new r("imentos",-1,1),new r("ivos",-1,8)],S=[new r("ada",-1,1),new r("ida",-1,1),new r("ia",-1,1),new r("aria",2,1),new r("eria",2,1),new r("iria",2,1),new r("ara",-1,1),new r("era",-1,1),new r("ira",-1,1),new r("ava",-1,1),new r("asse",-1,1),new r("esse",-1,1),new r("isse",-1,1),new r("aste",-1,1),new r("este",-1,1),new r("iste",-1,1),new r("ei",-1,1),new r("arei",16,1),new r("erei",16,1),new r("irei",16,1),new r("am",-1,1),new r("iam",20,1),new r("ariam",21,1),new r("eriam",21,1),new r("iriam",21,1),new r("aram",20,1),new r("eram",20,1),new r("iram",20,1),new r("avam",20,1),new r("em",-1,1),new r("arem",29,1),new r("erem",29,1),new r("irem",29,1),new r("assem",29,1),new r("essem",29,1),new r("issem",29,1),new r("ado",-1,1),new r("ido",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("indo",-1,1),new r("ara~o",-1,1),new r("era~o",-1,1),new r("ira~o",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("ir",-1,1),new r("as",-1,1),new r("adas",47,1),new r("idas",47,1),new r("ias",47,1),new r("arias",50,1),new r("erias",50,1),new r("irias",50,1),new r("aras",47,1),new r("eras",47,1),new r("iras",47,1),new r("avas",47,1),new r("es",-1,1),new r("ardes",58,1),new r("erdes",58,1),new r("irdes",58,1),new r("ares",58,1),new r("eres",58,1),new r("ires",58,1),new r("asses",58,1),new r("esses",58,1),new r("isses",58,1),new r("astes",58,1),new r("estes",58,1),new r("istes",58,1),new r("is",-1,1),new r("ais",71,1),new r("eis",71,1),new r("areis",73,1),new r("ereis",73,1),new r("ireis",73,1),new r("áreis",73,1),new r("éreis",73,1),new r("íreis",73,1),new r("ásseis",73,1),new r("ésseis",73,1),new r("ísseis",73,1),new r("áveis",73,1),new r("íeis",73,1),new r("aríeis",84,1),new r("eríeis",84,1),new r("iríeis",84,1),new r("ados",-1,1),new r("idos",-1,1),new r("amos",-1,1),new r("áramos",90,1),new r("éramos",90,1),new r("íramos",90,1),new r("ávamos",90,1),new r("íamos",90,1),new r("aríamos",95,1),new r("eríamos",95,1),new r("iríamos",95,1),new r("emos",-1,1),new r("aremos",99,1),new r("eremos",99,1),new r("iremos",99,1),new r("ássemos",99,1),new r("êssemos",99,1),new r("íssemos",99,1),new r("imos",-1,1),new r("armos",-1,1),new r("ermos",-1,1),new r("irmos",-1,1),new r("ámos",-1,1),new r("arás",-1,1),new r("erás",-1,1),new r("irás",-1,1),new r("eu",-1,1),new r("iu",-1,1),new r("ou",-1,1),new r("ará",-1,1),new r("erá",-1,1),new r("irá",-1,1)],W=[new r("a",-1,1),new r("i",-1,1),new r("o",-1,1),new r("os",-1,1),new r("á",-1,1),new r("í",-1,1),new r("ó",-1,1)],L=[new r("e",-1,1),new r("ç",-1,2),new r("é",-1,1),new r("ê",-1,1)],y=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],z=new s;this.setCurrent=function(e){z.setCurrent(e)},this.getCurrent=function(){return z.getCurrent()},this.stem=function(){var r=z.cursor;return e(),z.cursor=r,a(),z.limit_backward=r,z.cursor=z.limit,_(),z.cursor=z.limit,p(),z.cursor=z.limit_backward,u(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.ru.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Russian` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,t=new function(){function e(){for(;!W.in_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function t(){for(;!W.out_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function w(){b=W.limit,_=b,e()&&(b=W.cursor,t()&&e()&&t()&&(_=W.cursor))}function i(){return _<=W.cursor}function u(e,n){var r,t;if(W.ket=W.cursor,r=W.find_among_b(e,n)){switch(W.bra=W.cursor,r){case 1:if(t=W.limit-W.cursor,!W.eq_s_b(1,"а")&&(W.cursor=W.limit-t,!W.eq_s_b(1,"я")))return!1;case 2:W.slice_del()}return!0}return!1}function o(){return u(h,9)}function s(e,n){var r;return W.ket=W.cursor,!!(r=W.find_among_b(e,n))&&(W.bra=W.cursor,1==r&&W.slice_del(),!0)}function c(){return s(g,26)}function m(){return!!c()&&(u(C,8),!0)}function f(){return s(k,2)}function l(){return u(P,46)}function a(){s(v,36)}function p(){var e;W.ket=W.cursor,(e=W.find_among_b(F,2))&&(W.bra=W.cursor,i()&&1==e&&W.slice_del())}function d(){var e;if(W.ket=W.cursor,e=W.find_among_b(q,4))switch(W.bra=W.cursor,e){case 1:if(W.slice_del(),W.ket=W.cursor,!W.eq_s_b(1,"н"))break;W.bra=W.cursor;case 2:if(!W.eq_s_b(1,"н"))break;case 3:W.slice_del()}}var _,b,h=[new n("в",-1,1),new n("ив",0,2),new n("ыв",0,2),new n("вши",-1,1),new n("ивши",3,2),new n("ывши",3,2),new n("вшись",-1,1),new n("ившись",6,2),new n("ывшись",6,2)],g=[new n("ее",-1,1),new n("ие",-1,1),new n("ое",-1,1),new n("ые",-1,1),new n("ими",-1,1),new n("ыми",-1,1),new n("ей",-1,1),new n("ий",-1,1),new n("ой",-1,1),new n("ый",-1,1),new n("ем",-1,1),new n("им",-1,1),new n("ом",-1,1),new n("ым",-1,1),new n("его",-1,1),new n("ого",-1,1),new n("ему",-1,1),new n("ому",-1,1),new n("их",-1,1),new n("ых",-1,1),new n("ею",-1,1),new n("ою",-1,1),new n("ую",-1,1),new n("юю",-1,1),new n("ая",-1,1),new n("яя",-1,1)],C=[new n("ем",-1,1),new n("нн",-1,1),new n("вш",-1,1),new n("ивш",2,2),new n("ывш",2,2),new n("щ",-1,1),new n("ющ",5,1),new n("ующ",6,2)],k=[new n("сь",-1,1),new n("ся",-1,1)],P=[new n("ла",-1,1),new n("ила",0,2),new n("ыла",0,2),new n("на",-1,1),new n("ена",3,2),new n("ете",-1,1),new n("ите",-1,2),new n("йте",-1,1),new n("ейте",7,2),new n("уйте",7,2),new n("ли",-1,1),new n("или",10,2),new n("ыли",10,2),new n("й",-1,1),new n("ей",13,2),new n("уй",13,2),new n("л",-1,1),new n("ил",16,2),new n("ыл",16,2),new n("ем",-1,1),new n("им",-1,2),new n("ым",-1,2),new n("н",-1,1),new n("ен",22,2),new n("ло",-1,1),new n("ило",24,2),new n("ыло",24,2),new n("но",-1,1),new n("ено",27,2),new n("нно",27,1),new n("ет",-1,1),new n("ует",30,2),new n("ит",-1,2),new n("ыт",-1,2),new n("ют",-1,1),new n("уют",34,2),new n("ят",-1,2),new n("ны",-1,1),new n("ены",37,2),new n("ть",-1,1),new n("ить",39,2),new n("ыть",39,2),new n("ешь",-1,1),new n("ишь",-1,2),new n("ю",-1,2),new n("ую",44,2)],v=[new n("а",-1,1),new n("ев",-1,1),new n("ов",-1,1),new n("е",-1,1),new n("ие",3,1),new n("ье",3,1),new n("и",-1,1),new n("еи",6,1),new n("ии",6,1),new n("ами",6,1),new n("ями",6,1),new n("иями",10,1),new n("й",-1,1),new n("ей",12,1),new n("ией",13,1),new n("ий",12,1),new n("ой",12,1),new n("ам",-1,1),new n("ем",-1,1),new n("ием",18,1),new n("ом",-1,1),new n("ям",-1,1),new n("иям",21,1),new n("о",-1,1),new n("у",-1,1),new n("ах",-1,1),new n("ях",-1,1),new n("иях",26,1),new n("ы",-1,1),new n("ь",-1,1),new n("ю",-1,1),new n("ию",30,1),new n("ью",30,1),new n("я",-1,1),new n("ия",33,1),new n("ья",33,1)],F=[new n("ост",-1,1),new n("ость",-1,1)],q=[new n("ейше",-1,1),new n("н",-1,2),new n("ейш",-1,1),new n("ь",-1,3)],S=[33,65,8,232],W=new r;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){return w(),W.cursor=W.limit,!(W.cursor=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.sv.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Lunr languages, `Swedish` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.vi.min.js:
--------------------------------------------------------------------------------
1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}});
--------------------------------------------------------------------------------
/docs/site/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | None
4 | 2020-10-18
5 | daily
6 |
7 | None
8 | 2020-10-18
9 | daily
10 |
11 | None
12 | 2020-10-18
13 | daily
14 |
15 | None
16 | 2020-10-18
17 | daily
18 |
19 | None
20 | 2020-10-18
21 | daily
22 |
23 | None
24 | 2020-10-18
25 | daily
26 |
27 | None
28 | 2020-10-18
29 | daily
30 |
31 | None
32 | 2020-10-18
33 | daily
34 |
35 | None
36 | 2020-10-18
37 | daily
38 |
39 | None
40 | 2020-10-18
41 | daily
42 |
43 | None
44 | 2020-10-18
45 | daily
46 |
47 |
--------------------------------------------------------------------------------
/docs/site/sitemap.xml.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeBardian/tplink-smartdevices-netstandard/2566af2a3a184e9746934af5668c5ab9a8735b88/docs/site/sitemap.xml.gz
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/BoolConverter.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace TPLinkSmartDevices.Data
7 | {
8 | internal class BoolConverter : JsonConverter
9 | {
10 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
11 | {
12 | writer.WriteValue(((bool)value) ? 1 : 0);
13 | }
14 |
15 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
16 | {
17 | return reader.Value.ToString() == "1";
18 | }
19 |
20 | public override bool CanConvert(Type objectType)
21 | {
22 | return objectType == typeof(bool);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/BulbHSV.cs:
--------------------------------------------------------------------------------
1 | namespace TPLinkSmartDevices.Data
2 | {
3 | public class BulbHSV
4 | {
5 | public int Hue { get; set; }
6 | public int Saturation { get; set; }
7 | public int Value { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/CountDownRule/CountDownRule.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using TPLinkSmartDevices.Devices;
9 |
10 | namespace TPLinkSmartDevices.Data.CountDownRule
11 | {
12 | public class CountDownRule
13 | {
14 | ///
15 | /// identifier of CountDown rule
16 | ///
17 | [JsonProperty("id")]
18 | public string Id { get; internal set; }
19 |
20 | ///
21 | /// custom name of CountDown rule
22 | ///
23 | [JsonProperty("name")]
24 | public string Name { get; set; }
25 |
26 | ///
27 | /// if the rule is currently active or not
28 | ///
29 | [JsonProperty("enable")]
30 | [JsonConverter(typeof(BoolConverter))]
31 | public bool Enabled { get; set; }
32 |
33 | ///
34 | /// if the device should be powered on or off after the timer runs out
35 | ///
36 | [JsonProperty("act")]
37 | [JsonConverter(typeof(BoolConverter))]
38 | public bool PoweredOn { get; set; }
39 |
40 | ///
41 | /// delay in seconds after which the action triggers
42 | ///
43 | [JsonProperty("delay")]
44 | public int Delay { get; set; }
45 |
46 | public bool ShouldSerializeId()
47 | {
48 | return Id != null;
49 | }
50 | }
51 |
52 | internal static class CountDownExtensions
53 | {
54 | internal static async Task> RetrieveCountDownRules(this ICountDown device, string ns)
55 | {
56 | dynamic result = await ((TPLinkSmartDevice)device).Execute(ns, "get_rules").ConfigureAwait(false);
57 | string rule_list = Convert.ToString(result.rule_list);
58 | return JsonConvert.DeserializeObject>(rule_list);
59 | }
60 |
61 | internal static async Task AddCountDownRule(this ICountDown device, string ns, CountDownRule cdr)
62 | {
63 | JObject payload = JObject.FromObject(cdr);
64 | dynamic result = await ((TPLinkSmartDevice)device).Execute(ns, "add_rule", payload).ConfigureAwait(false);
65 | cdr.Id = (string)result.id;
66 | return cdr;
67 | }
68 |
69 | internal static async Task EditCountDownRule(this ICountDown device, string ns, CountDownRule cdr)
70 | {
71 | JObject payload = JObject.FromObject(cdr);
72 | dynamic result = await ((TPLinkSmartDevice)device).Execute(ns, "edit_rule", payload).ConfigureAwait(false);
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/CountDownRule/ICountDown.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using TPLinkSmartDevices.Data.CountDownRule;
6 |
7 | namespace TPLinkSmartDevices.Devices
8 | {
9 | interface ICountDown
10 | {
11 | List CountDownRules { get; }
12 | Task RetrieveCountDownRules();
13 | Task AddCountDownRule(CountDownRule cdr);
14 | Task EditCountDownRule(string id, bool? enabled = null, int? delay = null, bool? poweredOn = null, string name = null);
15 | Task EditCountDownRule(CountDownRule cdr);
16 | Task DeleteCountDownRule(string id);
17 | Task DeleteAllCountDownRules();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/DimmerOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace TPLinkSmartDevices.Devices
4 | {
5 | public class DimmerOptions
6 | {
7 | public DimmerOptions()
8 | {
9 | FadeOnTime = 2000;
10 | FadeOffTime = 2000;
11 | GentleOnTime = 2000;
12 | GentleOffTime = 2000;
13 | DoubleClickAction = DimmerMode.GentleOnOff;
14 | LongPressAction = DimmerMode.GentleOnOff;
15 | Mode = DimmerMode.GentleOnOff;
16 | }
17 |
18 | public int FadeOnTime { get; set; }
19 | public int FadeOffTime { get; set; }
20 | public int GentleOnTime { get; set; }
21 | public int GentleOffTime { get; set; }
22 |
23 | public DimmerMode DoubleClickAction { get; set; }
24 | public DimmerMode LongPressAction { get; set; }
25 | public DimmerMode Mode { get; set; }
26 | }
27 |
28 | public enum DimmerMode
29 | {
30 | GentleOnOff,
31 | InstantOnOff,
32 | Preset,
33 | None
34 | }
35 |
36 | public static class DimmerModeExtensions
37 | {
38 | public static string ToStr(this DimmerMode mode)
39 | {
40 | return mode switch
41 | {
42 | DimmerMode.None => "none",
43 | DimmerMode.GentleOnOff => "gentle_on_off",
44 | DimmerMode.InstantOnOff => "instant_on_off",
45 | DimmerMode.Preset => "customize_preset",
46 | _ => "",
47 | };
48 | }
49 |
50 | public static DimmerMode ToDimmerMode(this string str)
51 | {
52 | return str switch
53 | {
54 | "none" => DimmerMode.None,
55 | "gentle_on_off" => DimmerMode.GentleOnOff,
56 | "instant_on_off" => DimmerMode.InstantOnOff,
57 | "customize_preset" => DimmerMode.Preset,
58 | _ => throw new ArgumentException($"can't parse {str} to DimmerMode"),
59 | };
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/LightDetails.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace TPLinkSmartDevices.Data
7 | {
8 | public class LightDetails
9 | {
10 | [JsonProperty("lamp_beam_angle")]
11 | public int LampBeamAngle { get; set; }
12 |
13 | [JsonProperty("min_voltage")]
14 | public int MinVoltage { get; set; }
15 |
16 | [JsonProperty("max_voltage")]
17 | public int MaxVoltage { get; set; }
18 |
19 | [JsonProperty("max_lumens")]
20 | public int MaxLumens { get; set; }
21 |
22 | [JsonProperty("wattage")]
23 | public int Wattage { get; set; }
24 |
25 | [JsonProperty("incandescent_equivalent")]
26 | public int IncandescentEquivalent { get; set; }
27 |
28 | [JsonProperty("color_rendering_index")]
29 | public int ColorRenderingIndex { get; set; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/PowerData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace TPLinkSmartDevices.Data
8 | {
9 | ///
10 | /// Encapsulates JSON data structure for current energy use as metered by the HS110 Smart Energy Meter.
11 | ///
12 | public class PowerData
13 | {
14 | private readonly dynamic _powerData;
15 | private string _hwversion;
16 |
17 | public PowerData(dynamic powerData, string hwversion)
18 | {
19 | _powerData = powerData;
20 | _hwversion = hwversion;
21 | }
22 |
23 | ///
24 | /// Currently measured voltage in volts.
25 | ///
26 | public double Voltage => _hwversion.StartsWith("1") ? _powerData.voltage : _powerData.voltage_mv / 1000.0d;
27 |
28 | ///
29 | /// Currently measured current in amperes.
30 | ///
31 | public double Amperage => _hwversion.StartsWith("1") ? _powerData.current : _powerData.current_ma / 1000.0d;
32 |
33 | ///
34 | /// Currently measured power in watts.
35 | ///
36 | public double Power => _hwversion.StartsWith("1") ? _powerData.power : _powerData.power_mw / 1000.0d;
37 |
38 | ///
39 | /// Total power consumption in kilowatthours.
40 | ///
41 | public double Total => _hwversion.StartsWith("1") ? _powerData.total : _powerData.total_wh / 1000.0d;
42 |
43 | public int ErrorCode => _powerData.err_code;
44 |
45 | public override string ToString()
46 | {
47 | return $"{Voltage:0.00} Volt, {Amperage:0.00} Ampere, {Power:0.00} Watt";
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/Schedule/ISchedule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 |
6 | namespace TPLinkSmartDevices.Data.Schedule
7 | {
8 | interface ISchedule
9 | {
10 | List Schedules { get; }
11 | Task RetrieveSchedules();
12 | Task AddSchedule(Schedule schedule);
13 | Task EditSchedule(Schedule schedule);
14 | Task DeleteSchedule(string id);
15 | Task DeleteSchedules();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/Schedule/Schedule.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Runtime.Serialization;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using TPLinkSmartDevices.Devices;
9 |
10 | namespace TPLinkSmartDevices.Data.Schedule
11 | {
12 | public class Schedule
13 | {
14 | ///
15 | /// identifier of schedule
16 | ///
17 | [JsonProperty("id")]
18 | public string Id { get; set; }
19 |
20 | ///
21 | /// custom name of CountDown rule
22 | ///
23 | [JsonProperty("name")]
24 | public string Name { get; set; }
25 |
26 | ///
27 | /// start time option for schedule
28 | ///
29 | [JsonProperty("stime_opt")]
30 | public TimeOption StartTimeOption { get; set; }
31 |
32 | ///
33 | /// start time after midnight
34 | ///
35 | [JsonProperty("smin")]
36 | [JsonConverter(typeof(TimeSpanConverter))]
37 | public TimeSpan StartTime { get; set; }
38 |
39 | ///
40 | /// whether to turn device on or off at start of rule.
41 | /// 0 = turn off,
42 | /// 1 = turn on,
43 | /// -1 and 2: purpose still unknown
44 | ///
45 | [JsonProperty("sact")]
46 | public int StartAction { get; set; }
47 |
48 | ///
49 | /// end time option for schedule
50 | ///
51 | [JsonProperty("etime_opt")]
52 | public TimeOption EndTimeOption { get; set; }
53 |
54 | ///
55 | /// end time in minutes after midnight
56 | ///
57 | [JsonProperty("emin")]
58 | [JsonConverter(typeof(TimeSpanConverter))]
59 | public TimeSpan EndTime { get; set; }
60 |
61 | ///
62 | /// whether to turn device on or off at end of rule.
63 | /// 0 = turn off,
64 | /// 1 = turn on,
65 | /// -1 and 2: purpose still unknown
66 | ///
67 | [JsonProperty("eact")]
68 | public int EndAction { get; set; }
69 |
70 | ///
71 | /// days that rule should be active,
72 | ///
73 | [JsonProperty("wday")]
74 | [JsonConverter(typeof(WeekdayConverter))]
75 | public Weekdays Weekdays { get; set; }
76 |
77 | ///
78 | /// if the schdeule is currently active or not
79 | ///
80 | [JsonProperty("enable")]
81 | [JsonConverter(typeof(BoolConverter))]
82 | public bool Enabled { get; set; }
83 |
84 | ///
85 | /// whether the rule will be used more than one time.
86 | ///
87 | [JsonProperty("repeat")]
88 | [JsonConverter(typeof(BoolConverter))]
89 | //seems to be required to set to true, otherwise throws -3 protocol error
90 | public bool Repeat => true;
91 |
92 | [JsonProperty("s_light")]
93 | public object LightState => new { saturation = Saturation, hue = Hue, brightness = Brightness, color_temp = ColorTemp };
94 |
95 | ///
96 | /// sets saturation of bulb’s light output. values from 0 to 100 are accepted.
97 | ///
98 | [JsonIgnore]
99 | public int Saturation { get; set; }
100 |
101 | ///
102 | /// sets hue of bulb’s light output. values from 0 to 360 accepted.
103 | ///
104 | [JsonIgnore]
105 | public int Hue { get; set; }
106 |
107 | ///
108 | /// sets brightness of bulb’s light output. values from 0 to 100 are accepted.
109 | ///
110 | [JsonIgnore]
111 | public int Brightness { get; set; }
112 |
113 | ///
114 | /// sets brightness of bulb’s light output. values from 0 to 100 are accepted.
115 | ///
116 | [JsonIgnore]
117 | public int ColorTemp { get; set; }
118 |
119 | [JsonExtensionData]
120 | private IDictionary _additionalData = new Dictionary();
121 |
122 | [OnDeserialized]
123 | private void OnDeserialized(StreamingContext context)
124 | {
125 | if (_additionalData.ContainsKey("s_light"))
126 | {
127 | Hue = (int)_additionalData["s_light"]["hue"];
128 | Saturation = (int)_additionalData["s_light"]["saturation"];
129 | Brightness = (int)_additionalData["s_light"]["brightness"];
130 | ColorTemp = (int)_additionalData["s_light"]["color_temp"];
131 | }
132 | }
133 |
134 | public bool ShouldSerializeId()
135 | {
136 | return Id != null;
137 | }
138 |
139 | //TODO: additional unknown parameters: latitude, longitude, year, month, day, force, frequency, on_off, eoffset/soffset !!
140 | }
141 |
142 | internal class TimeSpanConverter : JsonConverter
143 | {
144 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
145 | {
146 | int timeSinceMidnight = Convert.ToInt32(((TimeSpan)value).TotalMinutes);
147 | if (timeSinceMidnight > 1440) throw new ArgumentException("invalid time span");
148 | writer.WriteValue(timeSinceMidnight);
149 | }
150 |
151 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
152 | {
153 | return TimeSpan.FromMinutes(Convert.ToDouble(reader.Value));
154 | }
155 |
156 | public override bool CanConvert(Type objectType)
157 | {
158 | return objectType == typeof(TimeSpan);
159 | }
160 | }
161 |
162 | internal static class SchedulesExtensions
163 | {
164 | internal static async Task> RetrieveSchedules(this ISchedule device, string ns)
165 | {
166 | dynamic result = await ((TPLinkSmartDevice)device).Execute(ns, "get_rules").ConfigureAwait(false);
167 | string rule_list = Convert.ToString(result.rule_list);
168 | return JsonConvert.DeserializeObject>(rule_list);
169 | }
170 |
171 | internal static async Task AddSchedule(this ISchedule device, string ns, Schedule schedule)
172 | {
173 | JObject payload = JObject.FromObject(schedule);
174 | if (ns == "schedule")
175 | {
176 | payload.Property("s_light")?.Remove();
177 | }
178 | dynamic result = await ((TPLinkSmartDevice)device).Execute(ns, "add_rule", payload).ConfigureAwait(false);
179 | schedule.Id = (string)result.id;
180 | device.Schedules.Add(schedule);
181 | }
182 |
183 | internal static async Task EditSchedule(this ISchedule device, string ns, Schedule schedule)
184 | {
185 | JObject payload = JObject.FromObject(schedule);
186 | dynamic result = await ((TPLinkSmartDevice)device).Execute(ns, "edit_rule", payload).ConfigureAwait(false);
187 | }
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/Schedule/TimeOption.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace TPLinkSmartDevices.Data.Schedule
6 | {
7 | public enum TimeOption
8 | {
9 | None = -1,
10 | Custom = 0,
11 | Sunrise = 1,
12 | Sunset = 2
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Data/Schedule/Weekdays.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 |
9 | namespace TPLinkSmartDevices.Data.Schedule
10 | {
11 | [Flags]
12 | public enum Weekdays
13 | {
14 | None = 0,
15 | Sunday = 1 << 0,
16 | Monday = 1 << 1,
17 | Tuesday = 1 << 2,
18 | Wednesday = 1 << 3,
19 | Thursday = 1 << 4,
20 | Friday = 1 << 5,
21 | Saturday = 1 << 6,
22 | WeekendDays = Sunday | Saturday,
23 | WorkDays = Monday | Tuesday | Wednesday | Thursday | Friday,
24 | EveryDay = WeekendDays | WorkDays
25 | }
26 |
27 | ///
28 | /// converts Weekdays flags to array of weekday bits. example: (Weekdays.Saturday | Weekdays.Monday) ==> [0, 1, 0, 0, 0, 0, 1]
29 | ///
30 | public class WeekdayConverter : JsonConverter
31 | {
32 |
33 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
34 | {
35 | Weekdays weekdays = (Weekdays)value;
36 |
37 | writer.WriteStartArray();
38 | for (int i = 0; i < 7; i++)
39 | {
40 | if (weekdays.HasFlag((Weekdays)(1 << i)))
41 | {
42 | writer.WriteValue(1);
43 | }
44 | else
45 | {
46 | writer.WriteValue(0);
47 | }
48 | }
49 | writer.WriteEndArray();
50 | }
51 |
52 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
53 | {
54 | Weekdays weekdays = Weekdays.None;
55 | if (reader.TokenType != JsonToken.StartArray)
56 | {
57 | return weekdays;
58 | }
59 | JArray daySource = JArray.Load(reader);
60 | for (int i = 0; i < daySource.Count; i++)
61 | {
62 | if ((int)daySource[i] == 0) continue;
63 |
64 | weekdays |= (Weekdays)(1 << i);
65 | }
66 |
67 | return weekdays;
68 | }
69 |
70 | public override bool CanWrite => true;
71 |
72 | public override bool CanConvert(Type objectType)
73 | {
74 | return false;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Devices/TPLinkSmartDevice.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Threading.Tasks;
4 | using TPLinkSmartDevices.Messaging;
5 |
6 | namespace TPLinkSmartDevices.Devices
7 | {
8 | public abstract class TPLinkSmartDevice
9 | {
10 | const byte INITIALIZATION_VECTOR = 171;
11 |
12 | public string Hostname { get; protected set; }
13 | public int Port { get; protected set; }
14 |
15 | public IMessageCache MessageCache { get; set; } = new TimeGatedMessageCache(2);
16 |
17 | public string SoftwareVersion { get; private set; }
18 | public string HardwareVersion { get; private set; }
19 | public string Type { get; private set; }
20 | public string Model { get; private set; }
21 | public string MacAddress { get; private set; }
22 | public string DevName { get; private set; }
23 | public string HardwareId { get; private set; }
24 | public string FirmwareId { get; private set; }
25 | public string DeviceId { get; private set; }
26 | public string OemId { get; private set; }
27 | public string CloudServer { get; private set; }
28 | public bool RemoteAccessEnabled { get; set; }
29 | public int RSSI { get; private set; }
30 | public double[] LocationLatLong { get; private set; }
31 |
32 | public string Alias { get; private set; }
33 |
34 | private DateTime CurrentTime {get; set; }
35 |
36 | protected TPLinkSmartDevice(string hostname, int port=9999)
37 | {
38 | Hostname = hostname;
39 | Port = port;
40 | }
41 |
42 | protected TPLinkSmartDevice() { }
43 |
44 | ///
45 | /// Refresh device information
46 | ///
47 | public async Task Refresh(dynamic sysInfo = null)
48 | {
49 | await GetCloudInfo().ConfigureAwait(false);
50 | if (sysInfo == null)
51 | sysInfo = await Execute("system", "get_sysinfo").ConfigureAwait(false);
52 |
53 | SoftwareVersion = sysInfo.sw_ver;
54 | HardwareVersion = sysInfo.hw_ver;
55 | Type = sysInfo.type;
56 | Model = sysInfo.model;
57 | MacAddress = sysInfo.mac;
58 | DevName = sysInfo.dev_name;
59 | Alias = sysInfo.alias;
60 | HardwareId = sysInfo.hwId;
61 | FirmwareId = sysInfo.fwId;
62 | DeviceId = sysInfo.deviceId;
63 | OemId = sysInfo.oemId;
64 | RSSI = sysInfo.rssi;
65 |
66 | if (sysInfo.latitude != null)
67 | LocationLatLong = new double[2] { sysInfo.latitude, sysInfo.longitude };
68 | else if (sysInfo.latitude_i != null)
69 | LocationLatLong = new double[2] { sysInfo.latitude_i, sysInfo.longitude_i };
70 | }
71 |
72 | ///
73 | /// Sends command to device and returns answer
74 | ///
75 | protected internal async Task Execute(string system, string command, object argument = null, object value = null)
76 | {
77 | var message = new SmartHomeProtocolMessage(system, command, argument, value);
78 | return await MessageCache.Request(message, Hostname, Port).ConfigureAwait(false);
79 | }
80 |
81 | protected internal async Task Execute(string system, string command, string json)
82 | {
83 | var message = new SmartHomeProtocolMessage(system, command, json);
84 | return await MessageCache.Request(message, Hostname, Port);
85 | }
86 |
87 | public async Task SetAlias(string value)
88 | {
89 | await Execute("system", "set_dev_alias", "alias", value).ConfigureAwait(false);
90 | this.Alias = value;
91 | }
92 |
93 | public async Task GetTime()
94 | {
95 | dynamic rawTime = await Execute("time", "get_time").ConfigureAwait(false);
96 | return new DateTime((int)rawTime.year, (int)rawTime.month, (int)rawTime.mday, (int)rawTime.hour, (int)rawTime.min, (int)rawTime.sec);
97 | }
98 |
99 | public async Task GetCloudInfo()
100 | {
101 | dynamic cloudInfo = await Execute("cnCloud", "get_info").ConfigureAwait(false);
102 | if (cloudInfo == null)
103 | {
104 | RemoteAccessEnabled = false;
105 | return;
106 | }
107 | CloudServer = (string)cloudInfo.server;
108 | RemoteAccessEnabled = Convert.ToBoolean((int)cloudInfo.binded);
109 | }
110 |
111 | ///
112 | /// Binds account to cloud server
113 | ///
114 | public async Task ConfigureRemoteAccess(string username, string password)
115 | {
116 | if (!RemoteAccessEnabled) await SetRemoteAccessEnabled(true).ConfigureAwait(false);
117 | try
118 | {
119 | dynamic result = await Execute("cnCloud", "bind", new JObject
120 | {
121 | new JProperty("username", username),
122 | new JProperty("password", password)
123 | }, null).ConfigureAwait(false);
124 | }
125 | catch (Exception e)
126 | {
127 | RemoteAccessEnabled = false;
128 | if (e.Message.Contains("20601") || e.Message.Contains("3"))
129 | {
130 | throw new Exception("The specified password is incorrect");
131 | }
132 | else if (e.Message.Contains("20600"))
133 | {
134 | throw new Exception("The username wasn't found");
135 | };
136 | throw new Exception("Internal error");
137 | }
138 | }
139 |
140 | ///
141 | /// Unbinds currently set account from cloud server
142 | ///
143 | public async Task UnbindRemoteAccess()
144 | {
145 | dynamic result = await Execute("cnCloud", "unbind").ConfigureAwait(false);
146 | await SetRemoteAccessEnabled(false).ConfigureAwait(false);
147 | }
148 |
149 | private async Task SetRemoteAccessEnabled(bool enabled, string server = "n-devs.tplinkcloud.com")
150 | {
151 | if (enabled)
152 | {
153 | dynamic result = await Execute("cnCloud", "set_server_url", "server", server).ConfigureAwait(false);
154 | RemoteAccessEnabled = true;
155 | }
156 | else
157 | {
158 | dynamic result = await Execute("cnCloud", "set_server_url", "server", "bogus.server.com").ConfigureAwait(false);
159 | RemoteAccessEnabled = false;
160 | }
161 | }
162 |
163 | public abstract Task SetPoweredOn(bool value);
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Devices/TPLinkSmartDimmer.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace TPLinkSmartDevices.Devices
9 | {
10 | public partial class TPLinkSmartDimmer : TPLinkSmartPlug
11 | {
12 | private DimmerOptions _options;
13 | private bool _poweredOn;
14 | private int _brightness;
15 | private int[] _presets;
16 |
17 | public bool PoweredOn => _poweredOn;
18 | public int Brightness => _brightness;
19 | public int[] Presets => _presets;
20 | public DimmerOptions Options => _options;
21 |
22 | [Obsolete("Use async factory method TPLinkSmartDimmer.Create() instead")]
23 | public TPLinkSmartDimmer(string hostName, int port = 9999, DimmerOptions opts = null) : base(hostName, port)
24 | {
25 | Task.Run(async () =>
26 | {
27 | this._options = opts ?? new DimmerOptions();
28 | await Refresh().ConfigureAwait(false);
29 | }).GetAwaiter().GetResult();
30 | }
31 |
32 | private TPLinkSmartDimmer() { }
33 |
34 | public static async Task Create(string hostname, int port = 9999, DimmerOptions opts = null)
35 | {
36 | var d = new TPLinkSmartDimmer() { Hostname = hostname, Port = port };
37 | d._options = opts ?? new DimmerOptions();
38 | await d.Refresh().ConfigureAwait(false);
39 | return d;
40 | }
41 |
42 | public new async Task Refresh()
43 | {
44 | dynamic sysInfo = await Execute("system", "get_sysinfo").ConfigureAwait(false);
45 | _poweredOn = (int)sysInfo.relay_state == 1;
46 | _brightness = (int)sysInfo.brightness;
47 |
48 | dynamic defaultBehavior = await Execute("smartlife.iot.dimmer", "get_default_behavior").ConfigureAwait(false);
49 | string long_press = (string)defaultBehavior.long_press.mode;
50 | string double_click = (string)defaultBehavior.double_click.mode;
51 | _options.LongPressAction = long_press.ToDimmerMode();
52 | _options.DoubleClickAction = double_click.ToDimmerMode();
53 |
54 | RetrievePresets(sysInfo);
55 | await Refresh((object)sysInfo).ConfigureAwait(false);
56 | }
57 |
58 | private void RetrievePresets(dynamic sysinfo)
59 | {
60 | JArray presets = JArray.Parse(Convert.ToString(sysinfo.preferred_state));
61 | _presets = presets.Select(x => (int)x["brightness"]).ToArray();
62 | }
63 |
64 | ///
65 | /// Set power state of dimming switch
66 | ///
67 | public override async Task SetPoweredOn(bool value)
68 | {
69 | await Execute("smartlife.iot.dimmer", "set_switch_state", "state", value ? 1 : 0).ConfigureAwait(false);
70 | _poweredOn = value;
71 | }
72 |
73 | ///
74 | /// Transition to a specified brightness level
75 | ///
76 | public async Task TransitionBrightness(int brightness, DimmerMode? mode = null, int? duration = null)
77 | {
78 | if (brightness < 0 || brightness > 100) throw new ArgumentException("brightness should be between 0 and 100");
79 |
80 | await Execute("smartlife.iot.dimmer", "set_dimmer_transition", new JObject
81 | {
82 | new JProperty("brightness", brightness),
83 | new JProperty("mode", (mode ?? _options.Mode).ToStr()),
84 | new JProperty("duration", duration ?? 1),
85 | }).ConfigureAwait(false);
86 | _brightness = brightness;
87 | }
88 |
89 | ///
90 | /// Instantly change plug to a specified brightness level
91 | ///
92 | public async Task SetBrightness(int brightness)
93 | {
94 | if (brightness < 0 || brightness > 100) throw new ArgumentException("brightness should be between 0 and 100");
95 |
96 | await Execute("smartlife.iot.dimmer", "set_brightness", "brightness", brightness).ConfigureAwait(false);
97 | _brightness = brightness;
98 | }
99 |
100 | ///
101 | /// Configures change mode on double click of switch
102 | ///
103 | public async Task SetDoubleClickAction(DimmerMode mode, int index=0)
104 | {
105 | if (mode == DimmerMode.Preset)
106 | {
107 | if (index < 0 || index > 3) throw new ArgumentException("index should be between 0 and 3");
108 |
109 | await Execute("smartlife.iot.dimmer", "set_double_click_action", new JObject
110 | {
111 | new JProperty("mode", mode.ToStr()),
112 | new JProperty("index", index)
113 | }).ConfigureAwait(false);
114 | }
115 | else
116 | await Execute("smartlife.iot.dimmer", "set_double_click_action", "mode", mode.ToStr()).ConfigureAwait(false);
117 |
118 | _options.DoubleClickAction = mode;
119 | }
120 |
121 | ///
122 | /// Configures change mode on long press of switch
123 | ///
124 | public async Task SetLongPressAction(DimmerMode mode, int index=0)
125 | {
126 | if (mode == DimmerMode.Preset)
127 | {
128 | if (index < 0 || index > 3) throw new ArgumentException("index should be between 0 and 3");
129 |
130 | await Execute("smartlife.iot.dimmer", "set_long_press_action", new JObject
131 | {
132 | new JProperty("mode", mode.ToStr()),
133 | new JProperty("index", index)
134 | }).ConfigureAwait(false);
135 | }
136 | else
137 | await Execute("smartlife.iot.dimmer", "set_long_press_action", "mode", mode.ToStr()).ConfigureAwait(false);
138 |
139 | _options.LongPressAction = mode;
140 | }
141 |
142 | ///
143 | /// Configures speed of fade on transition
144 | ///
145 | public async Task SetFadeOnTime(int fadeOnTime)
146 | {
147 | if (fadeOnTime < 0) throw new ArgumentException("fadeOnTime should be a positive number");
148 |
149 | await Execute("smartlife.iot.dimmer", "set_fade_on_time", "fadeTime", fadeOnTime).ConfigureAwait(false);
150 | _options.FadeOnTime = fadeOnTime;
151 | }
152 |
153 | ///
154 | /// Configures speed of fade off transition
155 | ///
156 | public async Task SetFadeOffTime(int fadeOffTime)
157 | {
158 | if (fadeOffTime < 0) throw new ArgumentException("fadeOffTime should be a positive number");
159 |
160 | await Execute("smartlife.iot.dimmer", "set_fade_on_time", "fadeTime", fadeOffTime).ConfigureAwait(false);
161 | _options.FadeOffTime = fadeOffTime;
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Devices/TPLinkSmartMeterPlug.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 | using TPLinkSmartDevices.Data;
6 |
7 | namespace TPLinkSmartDevices.Devices
8 | {
9 | public class TPLinkSmartMeterPlug : TPLinkSmartPlug
10 | {
11 | private const double WATTS_IN_KILOWATT = 1000d;
12 | private dynamic _gainData;
13 |
14 | public PowerData CurrentPowerUsage { get; private set; }
15 | public uint VGain => _gainData.vgain;
16 | public uint IGain => _gainData.igain;
17 |
18 | public TPLinkSmartMeterPlug(string hostname) : base(hostname)
19 | {
20 | Task.Run(async() =>
21 | {
22 | await Refresh();
23 | }).GetAwaiter().GetResult();
24 | }
25 |
26 | private TPLinkSmartMeterPlug() { }
27 |
28 | public static new async Task Create(string hostname, int port = 9999)
29 | {
30 | var p = new TPLinkSmartMeterPlug() { Hostname = hostname, Port = port };
31 | await p.Refresh().ConfigureAwait(false);
32 | return p;
33 | }
34 |
35 | public new async Task Refresh()
36 | {
37 | dynamic powerdata = await Execute("emeter", "get_realtime").ConfigureAwait(false);
38 | CurrentPowerUsage = new PowerData(powerdata , HardwareVersion);
39 | _gainData = await Execute("emeter", "get_vgain_igain").ConfigureAwait(false);
40 | await base.Refresh().ConfigureAwait(false);
41 | }
42 |
43 | ///
44 | /// Erases all emeter statistics
45 | ///
46 | public async Task EraseStats()
47 | {
48 | await Execute("emeter", "erase_emeter_stat").ConfigureAwait(false);
49 | }
50 |
51 | ///
52 | /// Query collected usage statistics from a specific month
53 | ///
54 | /// Dictionary<DateTime, float> of each day in a month and energy consumption of that day in kWh
55 | /// month of : ranging from 1(january) to 12(december)
56 | ///
57 | public async Task> GetMonthStats(int month, int year)
58 | {
59 | dynamic result = await Execute("emeter", "get_daystat", new JObject
60 | {
61 | new JProperty("month", month),
62 | new JProperty("year", year)
63 | }, null).ConfigureAwait(false);
64 | var stats = new Dictionary();
65 | foreach (dynamic day_stat in result.day_list)
66 | {
67 | stats.Add(new DateTime((int)day_stat.year, (int)day_stat.month, (int)day_stat.day), (float)(day_stat.energy ?? (day_stat.energy_wh / WATTS_IN_KILOWATT)));
68 | }
69 | return stats;
70 | }
71 |
72 | ///
73 | /// Query collected usage statistics over the course of a year
74 | ///
75 | /// Dictionary<int, float> of months and energy consumption in kWh
76 | /// year of stats
77 | public async Task> GetYearStats(int year)
78 | {
79 | if (year > DateTime.Now.Year || year < 2010) throw new ArgumentOutOfRangeException($"Can't get stats for {year}. Invalid year!");
80 |
81 | dynamic result = await Execute("emeter", "get_monthstat", "year", year).ConfigureAwait(false);
82 | var stats = new Dictionary();
83 | foreach (dynamic month_stat in result.month_list)
84 | {
85 | stats.Add((int)month_stat.month, (float)(month_stat.energy ?? (month_stat.energy_wh / WATTS_IN_KILOWATT)));
86 | }
87 | return stats;
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/tplink-smartdevices/Devices/TPLinkSmartMultiPlug.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace TPLinkSmartDevices.Devices
10 | {
11 | public class TPLinkSmartMultiPlug : TPLinkSmartDevice
12 | {
13 | ///
14 | /// If the all outlet relais are powered on
15 | ///
16 | public bool AllOutletsPowered { get; private set; }
17 |
18 | ///
19 | /// If the LED on the smart plug is on
20 | ///
21 | public bool LedOn { get; private set; }
22 |
23 | public string[] Features { get; private set; }
24 |
25 | public int OutletCount { get; private set; }
26 |
27 | public Outlet[] Outlets { get; private set; }
28 |
29 | public TPLinkSmartMultiPlug(string hostname, int port = 9999) : base(hostname, port)
30 | {
31 | Task.Run(() => Refresh()).GetAwaiter().GetResult();
32 | }
33 |
34 | private TPLinkSmartMultiPlug() { }
35 |
36 | public static async Task Create(string hostname, int port = 9999)
37 | {
38 | var p = new TPLinkSmartMultiPlug() { Hostname = hostname, Port = port };
39 | await p.Refresh().ConfigureAwait(false);
40 | return p;
41 | }
42 |
43 | ///
44 | /// Refresh device information
45 | ///
46 | public async Task Refresh()
47 | {
48 | dynamic sysInfo = await Execute("system", "get_sysinfo").ConfigureAwait(false);
49 |
50 | JObject info = JObject.Parse(Convert.ToString(sysInfo));
51 | bool hasChildren = info["children"] != null;
52 |
53 | if (!hasChildren) throw new Exception("This plug does not have multiple outlets. use TPLinkSmartPlug instead!");
54 |
55 | OutletCount = (int)sysInfo.child_num;
56 | Outlets = JsonConvert.DeserializeObject>(Convert.ToString(sysInfo.children)).ToArray();
57 | this.AllOutletsPowered = !this.Outlets.Any(o => o.OutletPowered == false);
58 |
59 | Features = ((string)sysInfo.feature).Split(':');
60 | LedOn = !(bool)sysInfo.led_off;
61 |
62 | await Refresh((object)sysInfo).ConfigureAwait(false);
63 | }
64 |
65 | public override async Task SetPoweredOn(bool value)
66 | {
67 | await Execute("system", "set_relay_state", "state", value ? 1 : 0).ConfigureAwait(false);
68 | this.AllOutletsPowered = value;
69 | }
70 |
71 | ///
72 | /// Send command which changes power state to plug
73 | ///
74 | public async Task SetPoweredOn(bool value, int outletId = -1)
75 | {
76 | if (outletId > OutletCount - 1 || outletId < -1) throw new ArgumentException("Plug does not have a outlet with specified id");
77 |
78 | //toggle all outlets of plug
79 | if (OutletCount == 1 || outletId == -1)
80 | {
81 | await Execute("system", "set_relay_state", "state", value ? 1 : 0).ConfigureAwait(false);
82 | this.AllOutletsPowered = value;
83 | }
84 | //toggle specific outlet
85 | else
86 | {
87 | JObject root = new JObject {
88 | new JProperty("context", new JObject { new JProperty("child_ids", GetPlugID(outletId)) }),
89 | new JProperty("system", new JObject {
90 | new JProperty("set_relay_state",
91 | new JObject { new JProperty("state", value ? 1 : 0) })
92 | })
93 | };
94 |
95 | string message = root.ToString(Formatting.None);
96 | await Execute("system", "set_relay_state", message).ConfigureAwait(false);
97 | this.Outlets[outletId].OutletPowered = value;
98 | this.AllOutletsPowered = !this.Outlets.Any(o => o.OutletPowered == false);
99 | }
100 | }
101 |
102 | private object GetPlugID(int outletId)
103 | {
104 | return JArray.FromObject(new[] { $"{DeviceId}0{outletId}" });
105 | }
106 |
107 | ///
108 | /// Send command which enables or disables night mode (LED state)
109 | ///
110 | public async Task SetLedOn(bool value)
111 | {
112 | await Execute("system", "set_led_off", "off", value ? 0 : 1).ConfigureAwait(false);
113 | this.LedOn = value;
114 | }
115 |
116 | public class Outlet
117 | {
118 | [JsonProperty("id")]
119 | public string Id { get; private set; }
120 |
121 | [JsonProperty("state")]
122 | public bool OutletPowered { get; set; }
123 |
124 | [JsonProperty("alias")]
125 | public string Alias { get; private set; }
126 |
127 | [JsonProperty("on_time")]
128 | public int OnTime { get; private set; }
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Devices/TPLinkSmartPlug.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using TPLinkSmartDevices.Data.CountDownRule;
8 | using TPLinkSmartDevices.Data.Schedule;
9 |
10 | namespace TPLinkSmartDevices.Devices
11 | {
12 | public class TPLinkSmartPlug : TPLinkSmartDevice, ICountDown, ISchedule
13 | {
14 | private const string COUNTDOWN_NAMESPACE = "count_down";
15 | private const string SCHEDULE_NAMESPACE = "schedule";
16 |
17 | ///
18 | /// If the outlet relay is powered on
19 | ///
20 | public bool OutletPowered { get; private set; }
21 |
22 | ///
23 | /// If the LED on the smart plug is on
24 | ///
25 | public bool LedOn { get; private set; }
26 |
27 | ///
28 | /// DateTime the relay was powered on
29 | ///
30 | public DateTime PoweredOnSince { get; private set; }
31 |
32 | public string[] Features { get; private set; }
33 |
34 | public List CountDownRules { get; private set; }
35 | public List Schedules { get; private set; }
36 |
37 | public TPLinkSmartPlug(string hostname, int port = 9999) : base(hostname, port)
38 | {
39 | Task.Run(() => Refresh()).GetAwaiter().GetResult();
40 | }
41 |
42 | protected TPLinkSmartPlug() { }
43 |
44 | public static async Task Create(string hostname, int port = 9999)
45 | {
46 | var p = new TPLinkSmartPlug() { Hostname = hostname, Port = port };
47 | await p.Refresh().ConfigureAwait(false);
48 | return p;
49 | }
50 |
51 | ///
52 | /// Refresh device information
53 | ///
54 | public async Task Refresh()
55 | {
56 | dynamic sysInfo = await Execute("system", "get_sysinfo").ConfigureAwait(false);
57 |
58 | JObject info = JObject.Parse(Convert.ToString(sysInfo));
59 | bool hasChildren = info["children"] != null;
60 |
61 | if (hasChildren) throw new Exception("this plug has multiple outlets. use TPLinkSmartMultiPlug instead!");
62 |
63 | OutletPowered = (int)sysInfo.relay_state == 1;
64 | Features = ((string)sysInfo.feature).Split(':');
65 | LedOn = !(bool)sysInfo.led_off;
66 |
67 | if ((int)sysInfo.on_time == 0)
68 | PoweredOnSince = default(DateTime);
69 | else
70 | PoweredOnSince = DateTime.Now - TimeSpan.FromSeconds((int)sysInfo.on_time);
71 |
72 | await RetrieveCountDownRules().ConfigureAwait(false);
73 | await RetrieveSchedules().ConfigureAwait(false);
74 | await Refresh((object)sysInfo).ConfigureAwait(false);
75 | }
76 |
77 | ///
78 | /// Send command which changes power state to plug
79 | ///
80 | public override async Task SetPoweredOn(bool value)
81 | {
82 | await Execute("system", "set_relay_state", "state", value ? 1 : 0).ConfigureAwait(false);
83 | this.OutletPowered = value;
84 | }
85 |
86 | ///
87 | /// Send command which changes power state to plug
88 | ///
89 | [Obsolete("Use TPLinkSmartPlug.SetPoweredOn(bool) instead")]
90 | public void SetOutletPowered(bool value)
91 | {
92 | Task.Run(async () =>
93 | {
94 | await Execute("system", "set_relay_state", "state", value ? 1 : 0).ConfigureAwait(false);
95 | this.OutletPowered = value;
96 | });
97 | }
98 |
99 | ///
100 | /// Send command which enables or disables night mode (LED state)
101 | ///
102 | public async Task SetLedOn(bool value)
103 | {
104 | await Execute("system", "set_led_off", "off", value ? 0 : 1).ConfigureAwait(false);
105 | this.LedOn = value;
106 | }
107 |
108 | public async Task RetrieveCountDownRules()
109 | {
110 | CountDownRules = await this.RetrieveCountDownRules(COUNTDOWN_NAMESPACE);
111 | }
112 |
113 | public async Task AddCountDownRule(CountDownRule cdr)
114 | {
115 | if (CountDownRules.Any(c => c.Id == cdr.Id)) throw new Exception("countdown rule with specified id already exists");
116 |
117 | cdr = await this.AddCountDownRule(COUNTDOWN_NAMESPACE, cdr);
118 | CountDownRules.Add(cdr);
119 | }
120 |
121 | public async Task EditCountDownRule(string id, bool? enabled = null, int? delay = null, bool? poweredOn = null, string name = null)
122 | {
123 | CountDownRule cdr = CountDownRules.Find(c => c.Id == id);
124 |
125 | if (cdr == null) throw new Exception("plug has no countdown rule with specified id");
126 |
127 | cdr.Enabled = enabled ?? cdr.Enabled;
128 | cdr.Delay = delay ?? cdr.Delay;
129 | cdr.PoweredOn = poweredOn ?? cdr.PoweredOn;
130 | cdr.Name = name ?? cdr.Name;
131 |
132 | await this.EditCountDownRule(COUNTDOWN_NAMESPACE, cdr);
133 | }
134 |
135 | public async Task EditCountDownRule(CountDownRule newCdr)
136 | {
137 | if (newCdr.Id == null) throw new Exception("countdown rule id is required");
138 | if (!CountDownRules.Any(c => c.Id == newCdr.Id)) throw new Exception("plug has no countdown rule with specified id");
139 |
140 | CountDownRule cdr = CountDownRules.Find(c => c.Id == newCdr.Id);
141 | cdr.Enabled = newCdr.Enabled;
142 | cdr.Delay = newCdr.Delay;
143 | cdr.PoweredOn = newCdr.PoweredOn;
144 | cdr.Name = newCdr.Name ?? cdr.Name;
145 |
146 | await this.EditCountDownRule(COUNTDOWN_NAMESPACE, cdr);
147 | }
148 |
149 |
150 | public async Task DeleteCountDownRule(string id)
151 | {
152 | dynamic result = await Execute(COUNTDOWN_NAMESPACE, "delete_rule", "id", id).ConfigureAwait(false);
153 |
154 | CountDownRules.RemoveAll(c => c.Id == id);
155 | }
156 |
157 | public async Task DeleteAllCountDownRules()
158 | {
159 | dynamic result = await Execute(COUNTDOWN_NAMESPACE, "delete_all_rules").ConfigureAwait(false);
160 |
161 | CountDownRules.Clear();
162 | }
163 |
164 | public async Task RetrieveSchedules()
165 | {
166 | Schedules = await this.RetrieveSchedules(SCHEDULE_NAMESPACE);
167 | }
168 |
169 | public async Task AddSchedule(Schedule schedule)
170 | {
171 | await this.AddSchedule(SCHEDULE_NAMESPACE, schedule);
172 | }
173 |
174 | public async Task EditSchedule(Schedule schedule)
175 | {
176 | await this.EditSchedule(SCHEDULE_NAMESPACE, schedule);
177 | }
178 |
179 | public async Task DeleteSchedule(string id)
180 | {
181 | dynamic result = await Execute(SCHEDULE_NAMESPACE, "delete_rule", "id", id).ConfigureAwait(false);
182 | Schedules.RemoveAll(c => c.Id == id);
183 | }
184 |
185 | public async Task DeleteSchedules()
186 | {
187 | dynamic result = await Execute(SCHEDULE_NAMESPACE, "delete_all_rules").ConfigureAwait(false);
188 | Schedules.Clear();
189 | }
190 | }
191 | }
--------------------------------------------------------------------------------
/tplink-smartdevices/Events/DeviceFoundEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using TPLinkSmartDevices.Devices;
5 |
6 | namespace TPLinkSmartDevices.Events
7 | {
8 | public class DeviceFoundEventArgs : EventArgs
9 | {
10 | public TPLinkSmartDevice Device;
11 |
12 | public DeviceFoundEventArgs(TPLinkSmartDevice device)
13 | {
14 | Device = device;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Messaging/IMessageCache.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace TPLinkSmartDevices.Messaging
4 | {
5 | public abstract class IMessageCache
6 | {
7 | public abstract Task Request(SmartHomeProtocolMessage message, string hostname, int port = 9999);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Messaging/ManualMessageCache.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 |
5 | namespace TPLinkSmartDevices.Messaging
6 | {
7 | public class ManualMessageCache : IMessageCache
8 | {
9 | private List _cache = new List();
10 |
11 | public void Flush()
12 | {
13 | _cache.Clear();
14 | }
15 |
16 | public override async Task Request(SmartHomeProtocolMessage message, string hostname, int port = 9999)
17 | {
18 | var cachedMessage = _cache.FirstOrDefault(c => c.Matches(message, hostname, port));
19 |
20 | if (cachedMessage != null)
21 | return cachedMessage;
22 |
23 | var result = await message.Execute(hostname, port).ConfigureAwait(false);
24 | _cache.Add(new MessageCacheItem(result, hostname, port));
25 | return result;
26 | }
27 |
28 | protected class MessageCacheItem
29 | {
30 | internal int Hash { get; set; }
31 | internal string Hostname { get; set; }
32 | internal int Port { get; set; }
33 | internal dynamic MessageResult { get; set; }
34 |
35 | internal MessageCacheItem(dynamic messageResult, string hostname, int port)
36 | {
37 | MessageResult = messageResult;
38 | Hostname = hostname;
39 | Port = port;
40 | }
41 |
42 | internal bool Matches(SmartHomeProtocolMessage message, string hostname, int port)
43 | {
44 | if (Hostname != hostname || Port != port)
45 | return false;
46 |
47 | return message.MessageHash == Hash;
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Messaging/NoMessageCache.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace TPLinkSmartDevices.Messaging
4 | {
5 | public class NoMessageCache : IMessageCache
6 | {
7 | public override async Task Request(SmartHomeProtocolMessage message, string hostname, int port = 9999)
8 | {
9 | return await message.Execute(hostname, port).ConfigureAwait(false);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Messaging/SmartHomeProtocolEncoder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 |
5 | namespace TPLinkSmartDevices.Messaging
6 | {
7 | internal static class SmartHomeProtocolEncoder
8 | {
9 | const byte INITIALIZATION_VECTOR = 171;
10 |
11 | internal static byte[] Encrypt(string data)
12 | {
13 | var encryptedMessage = Encrypt(Encoding.ASCII.GetBytes(data));
14 |
15 | var lengthBytes = BitConverter.GetBytes((UInt32)encryptedMessage.Length);
16 | if (BitConverter.IsLittleEndian) // this value needs to be in big-endian
17 | lengthBytes = lengthBytes.Reverse().ToArray();
18 |
19 | return lengthBytes.Concat(encryptedMessage).ToArray();
20 | }
21 |
22 | internal static byte[] Encrypt(byte[] data)
23 | {
24 | var result = new byte[data.Length];
25 | var key = INITIALIZATION_VECTOR; // TP-Link Constant
26 | for (int i = 0; i < data.Length; i++)
27 | {
28 | result[i] = (byte)(key ^ data[i]);
29 | key = result[i];
30 | }
31 |
32 | return result;
33 | }
34 |
35 | internal static byte[] Decrypt(byte[] data)
36 | {
37 | var buf = (byte[])data.Clone();
38 | var key = INITIALIZATION_VECTOR; // TP-Link Constant
39 | for (int i = 0; i < data.Length; i++)
40 | {
41 | var nextKey = buf[i];
42 | buf[i] = (byte)(key ^ buf[i]);
43 | key = nextKey;
44 | }
45 | return buf;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Messaging/SmartHomeProtocolMessage.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net.Sockets;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace TPLinkSmartDevices.Messaging
10 | {
11 | public class SmartHomeProtocolMessage
12 | {
13 | public int MessageHash
14 | {
15 | get
16 | {
17 | var data = Encoding.ASCII.GetBytes(Message ?? JSON);
18 | unchecked
19 | {
20 | const int p = 16777619;
21 | int hash = (int)2166136261;
22 |
23 | for (int i = 0; i < data.Length; i++)
24 | hash = (hash ^ data[i]) * p;
25 |
26 | hash += hash << 13;
27 | hash ^= hash >> 7;
28 | hash += hash << 3;
29 | hash ^= hash >> 17;
30 | hash += hash << 5;
31 | return hash;
32 | }
33 | }
34 | }
35 |
36 | public string JSON
37 | {
38 | get
39 | {
40 | object argObject;
41 | if (Value != null)
42 | argObject = new JObject { new JProperty(Argument.ToString(), Value) };
43 | else
44 | argObject = Argument;
45 |
46 | var root = new JObject { new JProperty(System, new JObject { new JProperty(Command, argObject) }) };
47 |
48 | return root.ToString(Newtonsoft.Json.Formatting.None);
49 | }
50 | }
51 |
52 | public string Message { get; private set; }
53 |
54 | public string System { get; private set; }
55 | public string Command { get; private set; }
56 | public object Argument { get; private set; }
57 | public object Value { get; private set; }
58 |
59 | internal SmartHomeProtocolMessage(string system, string command, object argument, object value)
60 | {
61 | System = system;
62 | Command = command;
63 | Argument = argument;
64 | Value = value;
65 | }
66 |
67 | internal SmartHomeProtocolMessage(string system, string command, string json)
68 | {
69 | Message = json;
70 | System = system;
71 | Command = command;
72 | }
73 |
74 | internal async Task Execute(string hostname, int port)
75 | {
76 | var messageToSend = SmartHomeProtocolEncoder.Encrypt(Message ?? JSON);
77 |
78 | var client = new TcpClient();
79 | await client.ConnectAsync(hostname, port).ConfigureAwait(false);
80 |
81 | byte[] packet = new byte[0];
82 | using (var stream = client.GetStream())
83 | {
84 | await stream.WriteAsync(messageToSend, 0, messageToSend.Length).ConfigureAwait(false);
85 |
86 | int targetSize = 0;
87 | var buffer = new List();
88 | while (true)
89 | {
90 | var chunk = new byte[1024];
91 | var bytesReceived = await stream.ReadAsync(chunk, 0, chunk.Length).ConfigureAwait(false);
92 |
93 | if (!buffer.Any())
94 | {
95 | var lengthBytes = chunk.Take(4).ToArray();
96 | if (BitConverter.IsLittleEndian)
97 | lengthBytes = lengthBytes.Reverse().ToArray();
98 | targetSize = (int)BitConverter.ToUInt32(lengthBytes, 0);
99 | }
100 | buffer.AddRange(chunk.Take(bytesReceived));
101 |
102 | if (buffer.Count == targetSize + 4)
103 | break;
104 | }
105 |
106 | packet = buffer.Skip(4).Take(targetSize).ToArray();
107 | }
108 | client.Dispose();
109 |
110 | var decrypted = Encoding.ASCII.GetString(SmartHomeProtocolEncoder.Decrypt(packet)).Trim('\0');
111 |
112 | var subResult = (dynamic)((JObject)JObject.Parse(decrypted)[System])[Command];
113 | if (subResult?["err_code"] != null && subResult?.err_code != 0)
114 | throw new Exception($"Protocol error {subResult.err_code} ({subResult.err_msg})");
115 |
116 | return subResult;
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/tplink-smartdevices/Messaging/TimeGatedMessageCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace TPLinkSmartDevices.Messaging
7 | {
8 | public class TimeGatedMessageCache : IMessageCache
9 | {
10 | public int TimeGateResetSeconds { get; set; } = 10;
11 |
12 | private List _cache = new List();
13 |
14 | public TimeGatedMessageCache(int resetTimeSeconds = 10)
15 | {
16 | TimeGateResetSeconds = resetTimeSeconds;
17 | }
18 |
19 | public override async Task Request(SmartHomeProtocolMessage message, string hostname, int port)
20 | {
21 | var cachedMessage = _cache.FirstOrDefault(c => c.Matches(message, hostname, port));
22 |
23 | if (cachedMessage != null)
24 | {
25 | if (cachedMessage.IsExpired(TimeGateResetSeconds))
26 | _cache.Remove(cachedMessage);
27 | else
28 | return cachedMessage.MessageResult;
29 | }
30 |
31 | var result = await message.Execute(hostname, port).ConfigureAwait(false);
32 | _cache.Add(new MessageCacheItem(result, hostname, port));
33 | return result;
34 | }
35 |
36 | protected class MessageCacheItem
37 | {
38 | internal int Hash { get; set; }
39 | internal string Hostname { get; set; }
40 | internal int Port { get; set; }
41 | internal dynamic MessageResult { get; set; }
42 | internal DateTime Cached { get; set; }
43 |
44 | internal MessageCacheItem(dynamic messageResult, string hostname, int port)
45 | {
46 | MessageResult = messageResult;
47 | Hostname = hostname;
48 | Port = port;
49 | Cached = DateTime.Now;
50 | }
51 |
52 | internal bool IsExpired(int expirySeconds)
53 | {
54 | return Cached.AddSeconds(expirySeconds) < DateTime.Now;
55 | }
56 |
57 | internal bool Matches(SmartHomeProtocolMessage message, string hostname, int port)
58 | {
59 | if (Hostname != hostname || Port != port)
60 | return false;
61 |
62 | return message.MessageHash == Hash;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tplink-smartdevices/TPLinkDiscovery.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using TPLinkSmartDevices.Devices;
10 | using Microsoft.CSharp.RuntimeBinder;
11 | using TPLinkSmartDevices.Events;
12 | using TPLinkSmartDevices.Messaging;
13 |
14 | namespace TPLinkSmartDevices
15 | {
16 | public class TPLinkDiscovery
17 | {
18 | public event EventHandler DeviceFound;
19 |
20 | private int PORT_NUMBER = 9999;
21 |
22 | public List DiscoveredDevices { get; private set; }
23 |
24 | private UdpClient udp;
25 |
26 | private bool discoveryComplete = false;
27 |
28 | public TPLinkDiscovery()
29 | {
30 | DiscoveredDevices = new List();
31 | }
32 |
33 | public async Task> Discover(int port=9999, int timeout=5000, string target = "255.255.255.255")
34 | {
35 | discoveryComplete = false;
36 |
37 | DiscoveredDevices.Clear();
38 | PORT_NUMBER = port;
39 |
40 | await SendDiscoveryRequestAsync(target).ConfigureAwait(false);
41 |
42 | udp = new UdpClient(PORT_NUMBER)
43 | {
44 | EnableBroadcast = true
45 | };
46 |
47 | return await Task.WhenAny(Task.Delay(timeout), Receive())
48 | .ContinueWith(t =>
49 | {
50 | discoveryComplete = true;
51 | udp.Close();
52 | udp = null;
53 |
54 | return DiscoveredDevices;
55 | })
56 | .ConfigureAwait(false);
57 | }
58 |
59 | private async Task Receive()
60 | {
61 | while (true)
62 | {
63 | if (discoveryComplete) //Prevent ObjectDisposedException/NullReferenceException when the Close() function is called
64 | return;
65 |
66 | IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT_NUMBER);
67 | UdpReceiveResult result = await udp.ReceiveAsync().ConfigureAwait(false);
68 | ip = result.RemoteEndPoint;
69 | var message = Encoding.ASCII.GetString(Messaging.SmartHomeProtocolEncoder.Decrypt(result.Buffer));
70 |
71 | TPLinkSmartDevice device = null;
72 | try
73 | {
74 | dynamic sys_info = ((dynamic)JObject.Parse(message)).system.get_sysinfo;
75 | string model = (string)sys_info.model;
76 | if (model != null)
77 | {
78 | if (model.StartsWith("HS110"))
79 | device = await TPLinkSmartMeterPlug.Create(ip.Address.ToString()).ConfigureAwait(false);
80 | else if (model.StartsWith("HS300") || model.StartsWith("KP303") || model.StartsWith("HS107"))
81 | device = await TPLinkSmartMultiPlug.Create(ip.Address.ToString()).ConfigureAwait(false);
82 | else if (model.StartsWith("HS220"))
83 | device = await TPLinkSmartDimmer.Create(ip.Address.ToString()).ConfigureAwait(false);
84 | else if (model.StartsWith("HS"))
85 | device = await TPLinkSmartPlug.Create(ip.Address.ToString()).ConfigureAwait(false);
86 | else if (model.StartsWith("KL") || model.StartsWith("LB"))
87 | device = await TPLinkSmartBulb.Create(ip.Address.ToString()).ConfigureAwait(false);
88 | }
89 | }
90 | catch (RuntimeBinderException)
91 | {
92 | //discovered wrong device
93 | }
94 |
95 | if (device != null)
96 | {
97 | DiscoveredDevices.Add(device);
98 | OnDeviceFound(device);
99 | }
100 | }
101 | }
102 |
103 | private async Task SendDiscoveryRequestAsync(string target)
104 | {
105 | UdpClient client = new UdpClient(PORT_NUMBER);
106 | IPEndPoint ip = new IPEndPoint(IPAddress.Parse(target), PORT_NUMBER);
107 |
108 | var discoveryJson = JObject.FromObject(new
109 | {
110 | system = new { get_sysinfo = (object)null },
111 | emeter = new { get_realtime = (object)null }
112 | }).ToString(Newtonsoft.Json.Formatting.None);
113 | var discoveryPacket = Messaging.SmartHomeProtocolEncoder.Encrypt(discoveryJson).ToArray();
114 |
115 | var bytes = discoveryPacket.Skip(4).ToArray();
116 | client.EnableBroadcast = true;
117 | await client.SendAsync(bytes, bytes.Length, ip).ConfigureAwait(false);
118 | client.Close();
119 | client.Dispose();
120 | }
121 |
122 | private void OnDeviceFound(TPLinkSmartDevice device)
123 | {
124 | DeviceFound?.Invoke(this, new DeviceFoundEventArgs(device));
125 | }
126 |
127 | ///
128 | /// Makes device connect to specified network. Host who runs the application needs to be connected to the open configuration network! (TP-Link_Smart Plug_XXXX or similar)
129 | ///
130 | public async Task Associate(string ssid, string password, int type = 3)
131 | {
132 | dynamic scan = await new SmartHomeProtocolMessage("netif","get_scaninfo","refresh","1").Execute("192.168.0.1", 9999).ConfigureAwait(false);
133 |
134 | if (scan == null || !scan.ToString().Contains(ssid))
135 | {
136 | throw new Exception("Couldn't find network!");
137 | }
138 |
139 | JArray networks = JArray.Parse(Convert.ToString(scan.ap_list));
140 | JToken network = networks.First(n => n["ssid"].ToString() == ssid);
141 | type = (int)network["key_type"];
142 |
143 | dynamic result = await new SmartHomeProtocolMessage("netif", "set_stainfo", new JObject
144 | {
145 | new JProperty("ssid", ssid),
146 | new JProperty("password", password),
147 | new JProperty("key_type", type)
148 | }, null).Execute("192.168.0.1", 9999).ConfigureAwait(false);
149 |
150 | if (result == null)
151 | {
152 | throw new Exception("Couldn't connect to network. Check password");
153 | }
154 | else if (result["err_code"] != null && result.err_code != 0)
155 | throw new Exception($"Protocol error {result.err_code} ({result.err_msg})");
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/tplink-smartdevices/TPLinkSmartDevices.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | tplink-smartdevices
6 | CodeBardian
7 |
8 | .NET Standard 2.0 Library for Discovering and Operating TP-Link Smart Devices (HS, LB and KL-series)
9 | https://github.com/CodeBardian/tplink-smartdevices-netstandard
10 | https://github.com/CodeBardian/tplink-smartdevices-netstandard
11 | TP-Link, Smart Home
12 | Apache-2.0
13 | GitHub
14 | TPLinkSmartDevices
15 | 2.0.1
16 | 8.0
17 |
18 |
19 |
20 | bin\release\netstandard2.0\tplink-smartdevices.xml
21 | 1701;1702;1591
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------