Compare commits
15 Commits
9ba81d944f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f75d85dbb7 | |||
| 1191c75402 | |||
| c28d600d37 | |||
| 3f94f9d18d | |||
| 325cb210f7 | |||
| 296b4010c0 | |||
| 3ca7b7df9a | |||
| b69691c84f | |||
| 10178de7c1 | |||
| 74e8480a68 | |||
| 139924db94 | |||
| 61e86b1e96 | |||
| 514486bb6c | |||
| 0e10462a99 | |||
| dbebcb85f2 |
717
.gitignore
vendored
Normal file
717
.gitignore
vendored
Normal file
@@ -0,0 +1,717 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# VS Code files for those working on multiple tools
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Windows Installer files from build outputs
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# VS Code files for those working on multiple tools
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Windows Installer files from build outputs
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# HTTP files (REST Client files)
|
||||||
|
*.http
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
docker-compose.override.yml
|
||||||
|
|
||||||
|
# Environment files
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
Binary file not shown.
@@ -1,995 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
|
|
||||||
IIS configuration sections.
|
|
||||||
|
|
||||||
For schema documentation, see
|
|
||||||
%IIS_BIN%\config\schema\IIS_schema.xml.
|
|
||||||
|
|
||||||
Please make a backup of this file before making any changes to it.
|
|
||||||
|
|
||||||
NOTE: The following environment variables are available to be used
|
|
||||||
within this file and are understood by the IIS Express.
|
|
||||||
|
|
||||||
%IIS_USER_HOME% - The IIS Express home directory for the user
|
|
||||||
%IIS_SITES_HOME% - The default home directory for sites
|
|
||||||
%IIS_BIN% - The location of the IIS Express binaries
|
|
||||||
%SYSTEMDRIVE% - The drive letter of %IIS_BIN%
|
|
||||||
|
|
||||||
-->
|
|
||||||
<configuration>
|
|
||||||
<!--
|
|
||||||
|
|
||||||
The <configSections> section controls the registration of sections.
|
|
||||||
Section is the basic unit of deployment, locking, searching and
|
|
||||||
containment for configuration settings.
|
|
||||||
|
|
||||||
Every section belongs to one section group.
|
|
||||||
A section group is a container of logically-related sections.
|
|
||||||
|
|
||||||
Sections cannot be nested.
|
|
||||||
Section groups may be nested.
|
|
||||||
|
|
||||||
<section
|
|
||||||
name="" [Required, Collection Key] [XML name of the section]
|
|
||||||
allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set]
|
|
||||||
overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode]
|
|
||||||
allowLocation="true" [true|false] [Allowed in location tags]
|
|
||||||
/>
|
|
||||||
|
|
||||||
The recommended way to unlock sections is by using a location tag:
|
|
||||||
<location path="Default Web Site" overrideMode="Allow">
|
|
||||||
<system.webServer>
|
|
||||||
<asp />
|
|
||||||
</system.webServer>
|
|
||||||
</location>
|
|
||||||
|
|
||||||
-->
|
|
||||||
<configSections>
|
|
||||||
<sectionGroup name="system.applicationHost">
|
|
||||||
<section name="applicationPools" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="customMetadata" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="listenerAdapters" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="log" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="serviceAutoStartProviders" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="sites" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="webLimits" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
</sectionGroup>
|
|
||||||
<sectionGroup name="system.webServer">
|
|
||||||
<section name="asp" overrideModeDefault="Deny" />
|
|
||||||
<section name="caching" overrideModeDefault="Allow" />
|
|
||||||
<section name="cgi" overrideModeDefault="Deny" />
|
|
||||||
<section name="defaultDocument" overrideModeDefault="Allow" />
|
|
||||||
<section name="directoryBrowse" overrideModeDefault="Allow" />
|
|
||||||
<section name="fastCgi" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="globalModules" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="handlers" overrideModeDefault="Deny" />
|
|
||||||
<section name="httpCompression" overrideModeDefault="Allow" allowDefinition="Everywhere" />
|
|
||||||
<section name="httpErrors" overrideModeDefault="Allow" />
|
|
||||||
<section name="httpLogging" overrideModeDefault="Deny" />
|
|
||||||
<section name="httpProtocol" overrideModeDefault="Allow" />
|
|
||||||
<section name="httpRedirect" overrideModeDefault="Allow" />
|
|
||||||
<section name="httpTracing" overrideModeDefault="Deny" />
|
|
||||||
<section name="isapiFilters" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
|
|
||||||
<section name="modules" allowDefinition="MachineToApplication" overrideModeDefault="Deny" />
|
|
||||||
<section name="applicationInitialization" allowDefinition="MachineToApplication" overrideModeDefault="Allow" />
|
|
||||||
<section name="odbcLogging" overrideModeDefault="Deny" />
|
|
||||||
<sectionGroup name="security">
|
|
||||||
<section name="access" overrideModeDefault="Deny" />
|
|
||||||
<section name="applicationDependencies" overrideModeDefault="Deny" />
|
|
||||||
<sectionGroup name="authentication">
|
|
||||||
<section name="anonymousAuthentication" overrideModeDefault="Deny" />
|
|
||||||
<section name="basicAuthentication" overrideModeDefault="Deny" />
|
|
||||||
<section name="clientCertificateMappingAuthentication" overrideModeDefault="Deny" />
|
|
||||||
<section name="digestAuthentication" overrideModeDefault="Deny" />
|
|
||||||
<section name="iisClientCertificateMappingAuthentication" overrideModeDefault="Deny" />
|
|
||||||
<section name="windowsAuthentication" overrideModeDefault="Deny" />
|
|
||||||
</sectionGroup>
|
|
||||||
<section name="authorization" overrideModeDefault="Allow" />
|
|
||||||
<section name="ipSecurity" overrideModeDefault="Deny" />
|
|
||||||
<section name="dynamicIpSecurity" overrideModeDefault="Deny" />
|
|
||||||
<section name="isapiCgiRestriction" allowDefinition="AppHostOnly" overrideModeDefault="Deny" />
|
|
||||||
<section name="requestFiltering" overrideModeDefault="Allow" />
|
|
||||||
</sectionGroup>
|
|
||||||
<section name="serverRuntime" overrideModeDefault="Deny" />
|
|
||||||
<section name="serverSideInclude" overrideModeDefault="Deny" />
|
|
||||||
<section name="staticContent" overrideModeDefault="Allow" />
|
|
||||||
<sectionGroup name="tracing">
|
|
||||||
<section name="traceFailedRequests" overrideModeDefault="Allow" />
|
|
||||||
<section name="traceProviderDefinitions" overrideModeDefault="Deny" />
|
|
||||||
</sectionGroup>
|
|
||||||
<section name="urlCompression" overrideModeDefault="Allow" />
|
|
||||||
<section name="validation" overrideModeDefault="Allow" />
|
|
||||||
<sectionGroup name="webdav">
|
|
||||||
<section name="globalSettings" overrideModeDefault="Deny" />
|
|
||||||
<section name="authoring" overrideModeDefault="Deny" />
|
|
||||||
<section name="authoringRules" overrideModeDefault="Deny" />
|
|
||||||
</sectionGroup>
|
|
||||||
<sectionGroup name="rewrite">
|
|
||||||
<section name="allowedServerVariables" overrideModeDefault="Deny" />
|
|
||||||
<section name="rules" overrideModeDefault="Allow" />
|
|
||||||
<section name="outboundRules" overrideModeDefault="Allow" />
|
|
||||||
<section name="globalRules" overrideModeDefault="Deny" allowDefinition="AppHostOnly" />
|
|
||||||
<section name="providers" overrideModeDefault="Allow" />
|
|
||||||
<section name="rewriteMaps" overrideModeDefault="Allow" />
|
|
||||||
</sectionGroup>
|
|
||||||
<section name="webSocket" overrideModeDefault="Deny" />
|
|
||||||
<section name="aspNetCore" overrideModeDefault="Allow" />
|
|
||||||
</sectionGroup>
|
|
||||||
</configSections>
|
|
||||||
<configProtectedData>
|
|
||||||
<providers>
|
|
||||||
<add name="IISWASOnlyRsaProvider" type="" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useMachineContainer="true" useOAEP="false" />
|
|
||||||
<add name="AesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisConfigurationKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAA/HKxkz6alrlAPez0IUgujj/6k3WxCDriHp6jvpv3yEZmo7h6SMzGLxo4mTrIQVHSkB7tmElHKfUFTzE2BWF7nFWHY6Z6qmGBauFzwJMwESjril7Gjz69RBFH259HQ6aRDq9Xfx7U7H4HtdmnKNqGjgl/hwPQBGeIlWiDh+sYv3vKB0QU971tjX6H2B+9armlnC8UOuA6JYMDMI/VLLL16sng0fWAy5JYe0YVABVjiAWDW264RZW9Tr1Oax4qHZKg+SdjULxeOc2YmpX+d0yeITo1HkPF1hN1gHpIPIUDo05ilHUNfR3OkjVCIQK4cFKCq1s8NH+y+13MxUC4Fn1AlQ==" />
|
|
||||||
<add name="IISWASOnlyAesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAALmU8lTC+v2qtfQiiiquvvLpUQqKLEXs+jSKoWCM/uPhyB++k4dwug19mGidNK5FYiWK2KYE1yhjVJcbp12E98Q0R2nT7eBiCMY2JairxQ591rqABK7keGaIjwH7PwGzSpILl3RJ4YFvJ/7ZXEJxeDZIjW8ZxWVXx+/VyHs9U3WguLEkgMUX3jrxJi8LouxaIVPJAv/YQ1ZCWs8zImitxX/C/7o7yaIxznfsN5nGQzQfpUDPeby99aw2zPVTtZI2LaWIBON8guABvZ6JtJVDWmfdK6sodbnwdZkr6/Z2rfvamT1dC1SpQrGG7ulR/f9/GXvCaW10ZVKxekBF/CYlNMg==" />
|
|
||||||
</providers>
|
|
||||||
</configProtectedData>
|
|
||||||
<system.applicationHost>
|
|
||||||
<applicationPools>
|
|
||||||
<add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
|
|
||||||
<add name="Clr4ClassicAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
|
|
||||||
<add name="Clr2IntegratedAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
|
|
||||||
<add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
|
|
||||||
<add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />
|
|
||||||
<add name="GreenHome.Api AppPool" managedRuntimeVersion="" />
|
|
||||||
<applicationPoolDefaults managedRuntimeVersion="v4.0">
|
|
||||||
<processModel loadUserProfile="true" setProfileEnvironment="false" />
|
|
||||||
</applicationPoolDefaults>
|
|
||||||
</applicationPools>
|
|
||||||
<!--
|
|
||||||
|
|
||||||
The <listenerAdapters> section defines the protocols with which the
|
|
||||||
Windows Process Activation Service (WAS) binds.
|
|
||||||
|
|
||||||
-->
|
|
||||||
<listenerAdapters>
|
|
||||||
<add name="http" />
|
|
||||||
</listenerAdapters>
|
|
||||||
<sites>
|
|
||||||
<site name="WebSite1" id="1" serverAutoStart="true">
|
|
||||||
<application path="/">
|
|
||||||
<virtualDirectory path="/" physicalPath="%IIS_SITES_HOME%\WebSite1" />
|
|
||||||
</application>
|
|
||||||
<bindings>
|
|
||||||
<binding protocol="http" bindingInformation=":8080:localhost" />
|
|
||||||
</bindings>
|
|
||||||
</site>
|
|
||||||
<site name="GreenHome.Api" id="2">
|
|
||||||
<application path="/" applicationPool="GreenHome.Api AppPool">
|
|
||||||
<virtualDirectory path="/" physicalPath="D:\Data\Projects\php\greenhome\src\GreenHome.Api" />
|
|
||||||
</application>
|
|
||||||
<bindings>
|
|
||||||
<binding protocol="http" bindingInformation="*:62250:localhost" />
|
|
||||||
<binding protocol="https" bindingInformation="*:44315:localhost" />
|
|
||||||
</bindings>
|
|
||||||
</site>
|
|
||||||
<siteDefaults>
|
|
||||||
<!-- To enable logging, please change the below attribute "enabled" to "true" -->
|
|
||||||
<logFile logFormat="W3C" directory="%AppData%\Microsoft\IISExpressLogs" enabled="false" />
|
|
||||||
<traceFailedRequestsLogging directory="%AppData%\Microsoft" enabled="false" maxLogFileSizeKB="1024" />
|
|
||||||
</siteDefaults>
|
|
||||||
<applicationDefaults applicationPool="Clr4IntegratedAppPool" />
|
|
||||||
<virtualDirectoryDefaults allowSubDirConfig="true" />
|
|
||||||
</sites>
|
|
||||||
<webLimits />
|
|
||||||
</system.applicationHost>
|
|
||||||
<system.webServer>
|
|
||||||
<serverRuntime />
|
|
||||||
<asp scriptErrorSentToBrowser="true">
|
|
||||||
<cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" />
|
|
||||||
<limits />
|
|
||||||
</asp>
|
|
||||||
<caching enabled="true" enableKernelCache="true"></caching>
|
|
||||||
<cgi />
|
|
||||||
<defaultDocument enabled="true">
|
|
||||||
<files>
|
|
||||||
<add value="Default.htm" />
|
|
||||||
<add value="Default.asp" />
|
|
||||||
<add value="index.htm" />
|
|
||||||
<add value="index.html" />
|
|
||||||
<add value="iisstart.htm" />
|
|
||||||
<add value="default.aspx" />
|
|
||||||
</files>
|
|
||||||
</defaultDocument>
|
|
||||||
<directoryBrowse enabled="false" />
|
|
||||||
<fastCgi />
|
|
||||||
<!--
|
|
||||||
|
|
||||||
The <globalModules> section defines all native-code modules.
|
|
||||||
To enable a module, specify it in the <modules> section.
|
|
||||||
|
|
||||||
-->
|
|
||||||
<globalModules>
|
|
||||||
<add name="HttpLoggingModule" image="%IIS_BIN%\loghttp.dll" />
|
|
||||||
<add name="UriCacheModule" image="%IIS_BIN%\cachuri.dll" />
|
|
||||||
<add name="TokenCacheModule" image="%IIS_BIN%\cachtokn.dll" />
|
|
||||||
<add name="DynamicCompressionModule" image="%IIS_BIN%\compdyn.dll" />
|
|
||||||
<add name="StaticCompressionModule" image="%IIS_BIN%\compstat.dll" />
|
|
||||||
<add name="DefaultDocumentModule" image="%IIS_BIN%\defdoc.dll" />
|
|
||||||
<add name="DirectoryListingModule" image="%IIS_BIN%\dirlist.dll" />
|
|
||||||
<add name="ProtocolSupportModule" image="%IIS_BIN%\protsup.dll" />
|
|
||||||
<add name="HttpRedirectionModule" image="%IIS_BIN%\redirect.dll" />
|
|
||||||
<add name="ServerSideIncludeModule" image="%IIS_BIN%\iis_ssi.dll" />
|
|
||||||
<add name="StaticFileModule" image="%IIS_BIN%\static.dll" />
|
|
||||||
<add name="AnonymousAuthenticationModule" image="%IIS_BIN%\authanon.dll" />
|
|
||||||
<add name="CertificateMappingAuthenticationModule" image="%IIS_BIN%\authcert.dll" />
|
|
||||||
<add name="UrlAuthorizationModule" image="%IIS_BIN%\urlauthz.dll" />
|
|
||||||
<add name="BasicAuthenticationModule" image="%IIS_BIN%\authbas.dll" />
|
|
||||||
<add name="WindowsAuthenticationModule" image="%IIS_BIN%\authsspi.dll" />
|
|
||||||
<add name="IISCertificateMappingAuthenticationModule" image="%IIS_BIN%\authmap.dll" />
|
|
||||||
<add name="IpRestrictionModule" image="%IIS_BIN%\iprestr.dll" />
|
|
||||||
<add name="DynamicIpRestrictionModule" image="%IIS_BIN%\diprestr.dll" />
|
|
||||||
<add name="RequestFilteringModule" image="%IIS_BIN%\modrqflt.dll" />
|
|
||||||
<add name="CustomLoggingModule" image="%IIS_BIN%\logcust.dll" />
|
|
||||||
<add name="CustomErrorModule" image="%IIS_BIN%\custerr.dll" />
|
|
||||||
<add name="FailedRequestsTracingModule" image="%IIS_BIN%\iisfreb.dll" />
|
|
||||||
<add name="RequestMonitorModule" image="%IIS_BIN%\iisreqs.dll" />
|
|
||||||
<add name="IsapiModule" image="%IIS_BIN%\isapi.dll" />
|
|
||||||
<add name="IsapiFilterModule" image="%IIS_BIN%\filter.dll" />
|
|
||||||
<add name="CgiModule" image="%IIS_BIN%\cgi.dll" />
|
|
||||||
<add name="FastCgiModule" image="%IIS_BIN%\iisfcgi.dll" />
|
|
||||||
<!-- <add name="WebDAVModule" image="%IIS_BIN%\webdav.dll" /> -->
|
|
||||||
<add name="RewriteModule" image="%IIS_BIN%\rewrite.dll" />
|
|
||||||
<add name="ConfigurationValidationModule" image="%IIS_BIN%\validcfg.dll" />
|
|
||||||
<add name="WebSocketModule" image="%IIS_BIN%\iiswsock.dll" />
|
|
||||||
<add name="WebMatrixSupportModule" image="%IIS_BIN%\webmatrixsup.dll" />
|
|
||||||
<add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness32" />
|
|
||||||
<add name="ManagedEngine64" image="%windir%\Microsoft.NET\Framework64\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness64" />
|
|
||||||
<add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" />
|
|
||||||
<add name="ManagedEngineV4.0_64bit" image="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness64" />
|
|
||||||
<add name="ApplicationInitializationModule" image="%IIS_BIN%\warmup.dll" />
|
|
||||||
<add name="AspNetCoreModuleV2" image="%IIS_BIN%\Asp.Net Core Module\V2\aspnetcorev2.dll" />
|
|
||||||
</globalModules>
|
|
||||||
<httpCompression directory="%TEMP%">
|
|
||||||
<scheme name="gzip" dll="%IIS_BIN%\gzip.dll" />
|
|
||||||
<dynamicTypes>
|
|
||||||
<add mimeType="text/*" enabled="true" />
|
|
||||||
<add mimeType="message/*" enabled="true" />
|
|
||||||
<add mimeType="application/x-javascript" enabled="true" />
|
|
||||||
<add mimeType="application/javascript" enabled="true" />
|
|
||||||
<add mimeType="*/*" enabled="false" />
|
|
||||||
</dynamicTypes>
|
|
||||||
<staticTypes>
|
|
||||||
<add mimeType="text/*" enabled="true" />
|
|
||||||
<add mimeType="message/*" enabled="true" />
|
|
||||||
<add mimeType="application/javascript" enabled="true" />
|
|
||||||
<add mimeType="application/atom+xml" enabled="true" />
|
|
||||||
<add mimeType="application/xaml+xml" enabled="true" />
|
|
||||||
<add mimeType="image/svg+xml" enabled="true" />
|
|
||||||
<add mimeType="*/*" enabled="false" />
|
|
||||||
</staticTypes>
|
|
||||||
</httpCompression>
|
|
||||||
<httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath">
|
|
||||||
<error statusCode="401" prefixLanguageFilePath="%IIS_BIN%\custerr" path="401.htm" />
|
|
||||||
<error statusCode="403" prefixLanguageFilePath="%IIS_BIN%\custerr" path="403.htm" />
|
|
||||||
<error statusCode="404" prefixLanguageFilePath="%IIS_BIN%\custerr" path="404.htm" />
|
|
||||||
<error statusCode="405" prefixLanguageFilePath="%IIS_BIN%\custerr" path="405.htm" />
|
|
||||||
<error statusCode="406" prefixLanguageFilePath="%IIS_BIN%\custerr" path="406.htm" />
|
|
||||||
<error statusCode="412" prefixLanguageFilePath="%IIS_BIN%\custerr" path="412.htm" />
|
|
||||||
<error statusCode="500" prefixLanguageFilePath="%IIS_BIN%\custerr" path="500.htm" />
|
|
||||||
<error statusCode="501" prefixLanguageFilePath="%IIS_BIN%\custerr" path="501.htm" />
|
|
||||||
<error statusCode="502" prefixLanguageFilePath="%IIS_BIN%\custerr" path="502.htm" />
|
|
||||||
</httpErrors>
|
|
||||||
<httpLogging dontLog="false" />
|
|
||||||
<httpProtocol>
|
|
||||||
<customHeaders>
|
|
||||||
<clear />
|
|
||||||
<add name="X-Powered-By" value="ASP.NET" />
|
|
||||||
</customHeaders>
|
|
||||||
<redirectHeaders>
|
|
||||||
<clear />
|
|
||||||
</redirectHeaders>
|
|
||||||
</httpProtocol>
|
|
||||||
<httpRedirect enabled="false" />
|
|
||||||
<httpTracing />
|
|
||||||
<isapiFilters>
|
|
||||||
<filter name="ASP.Net_2.0.50727-64" path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness64,runtimeVersionv2.0" />
|
|
||||||
<filter name="ASP.Net_2.0.50727.0" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv2.0" />
|
|
||||||
<filter name="ASP.Net_2.0_for_v1.1" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="runtimeVersionv1.1" />
|
|
||||||
<filter name="ASP.Net_4.0_32bit" path="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv4.0" />
|
|
||||||
<filter name="ASP.Net_4.0_64bit" path="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness64,runtimeVersionv4.0" />
|
|
||||||
</isapiFilters>
|
|
||||||
<odbcLogging />
|
|
||||||
<security>
|
|
||||||
<access sslFlags="None" />
|
|
||||||
<applicationDependencies>
|
|
||||||
<application name="Active Server Pages" groupId="ASP" />
|
|
||||||
</applicationDependencies>
|
|
||||||
<authentication>
|
|
||||||
<anonymousAuthentication enabled="true" userName="" />
|
|
||||||
<basicAuthentication enabled="false" />
|
|
||||||
<clientCertificateMappingAuthentication enabled="false" />
|
|
||||||
<digestAuthentication enabled="false" />
|
|
||||||
<iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>
|
|
||||||
<windowsAuthentication enabled="false">
|
|
||||||
<providers>
|
|
||||||
<add value="Negotiate" />
|
|
||||||
<add value="NTLM" />
|
|
||||||
</providers>
|
|
||||||
</windowsAuthentication>
|
|
||||||
</authentication>
|
|
||||||
<authorization>
|
|
||||||
<add accessType="Allow" users="*" />
|
|
||||||
</authorization>
|
|
||||||
<ipSecurity allowUnlisted="true" />
|
|
||||||
<isapiCgiRestriction notListedIsapisAllowed="true" notListedCgisAllowed="true">
|
|
||||||
<add path="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" />
|
|
||||||
<add path="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" />
|
|
||||||
<add path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
|
|
||||||
<add path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
|
|
||||||
</isapiCgiRestriction>
|
|
||||||
<requestFiltering>
|
|
||||||
<fileExtensions allowUnlisted="true" applyToWebDAV="true">
|
|
||||||
<add fileExtension=".asa" allowed="false" />
|
|
||||||
<add fileExtension=".asax" allowed="false" />
|
|
||||||
<add fileExtension=".ascx" allowed="false" />
|
|
||||||
<add fileExtension=".master" allowed="false" />
|
|
||||||
<add fileExtension=".skin" allowed="false" />
|
|
||||||
<add fileExtension=".browser" allowed="false" />
|
|
||||||
<add fileExtension=".sitemap" allowed="false" />
|
|
||||||
<add fileExtension=".config" allowed="false" />
|
|
||||||
<add fileExtension=".cs" allowed="false" />
|
|
||||||
<add fileExtension=".csproj" allowed="false" />
|
|
||||||
<add fileExtension=".vb" allowed="false" />
|
|
||||||
<add fileExtension=".vbproj" allowed="false" />
|
|
||||||
<add fileExtension=".webinfo" allowed="false" />
|
|
||||||
<add fileExtension=".licx" allowed="false" />
|
|
||||||
<add fileExtension=".resx" allowed="false" />
|
|
||||||
<add fileExtension=".resources" allowed="false" />
|
|
||||||
<add fileExtension=".mdb" allowed="false" />
|
|
||||||
<add fileExtension=".vjsproj" allowed="false" />
|
|
||||||
<add fileExtension=".java" allowed="false" />
|
|
||||||
<add fileExtension=".jsl" allowed="false" />
|
|
||||||
<add fileExtension=".ldb" allowed="false" />
|
|
||||||
<add fileExtension=".dsdgm" allowed="false" />
|
|
||||||
<add fileExtension=".ssdgm" allowed="false" />
|
|
||||||
<add fileExtension=".lsad" allowed="false" />
|
|
||||||
<add fileExtension=".ssmap" allowed="false" />
|
|
||||||
<add fileExtension=".cd" allowed="false" />
|
|
||||||
<add fileExtension=".dsprototype" allowed="false" />
|
|
||||||
<add fileExtension=".lsaprototype" allowed="false" />
|
|
||||||
<add fileExtension=".sdm" allowed="false" />
|
|
||||||
<add fileExtension=".sdmDocument" allowed="false" />
|
|
||||||
<add fileExtension=".mdf" allowed="false" />
|
|
||||||
<add fileExtension=".ldf" allowed="false" />
|
|
||||||
<add fileExtension=".ad" allowed="false" />
|
|
||||||
<add fileExtension=".dd" allowed="false" />
|
|
||||||
<add fileExtension=".ldd" allowed="false" />
|
|
||||||
<add fileExtension=".sd" allowed="false" />
|
|
||||||
<add fileExtension=".adprototype" allowed="false" />
|
|
||||||
<add fileExtension=".lddprototype" allowed="false" />
|
|
||||||
<add fileExtension=".exclude" allowed="false" />
|
|
||||||
<add fileExtension=".refresh" allowed="false" />
|
|
||||||
<add fileExtension=".compiled" allowed="false" />
|
|
||||||
<add fileExtension=".msgx" allowed="false" />
|
|
||||||
<add fileExtension=".vsdisco" allowed="false" />
|
|
||||||
<add fileExtension=".rules" allowed="false" />
|
|
||||||
</fileExtensions>
|
|
||||||
<verbs allowUnlisted="true" applyToWebDAV="true" />
|
|
||||||
<hiddenSegments applyToWebDAV="true">
|
|
||||||
<add segment="web.config" />
|
|
||||||
<add segment="bin" />
|
|
||||||
<add segment="App_code" />
|
|
||||||
<add segment="App_GlobalResources" />
|
|
||||||
<add segment="App_LocalResources" />
|
|
||||||
<add segment="App_WebReferences" />
|
|
||||||
<add segment="App_Data" />
|
|
||||||
<add segment="App_Browsers" />
|
|
||||||
</hiddenSegments>
|
|
||||||
</requestFiltering>
|
|
||||||
</security>
|
|
||||||
<serverSideInclude ssiExecDisable="false" />
|
|
||||||
<staticContent lockAttributes="isDocFooterFileName">
|
|
||||||
<mimeMap fileExtension=".323" mimeType="text/h323" />
|
|
||||||
<mimeMap fileExtension=".3g2" mimeType="video/3gpp2" />
|
|
||||||
<mimeMap fileExtension=".3gp2" mimeType="video/3gpp2" />
|
|
||||||
<mimeMap fileExtension=".3gp" mimeType="video/3gpp" />
|
|
||||||
<mimeMap fileExtension=".3gpp" mimeType="video/3gpp" />
|
|
||||||
<mimeMap fileExtension=".aac" mimeType="audio/aac" />
|
|
||||||
<mimeMap fileExtension=".aaf" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".aca" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".accdb" mimeType="application/msaccess" />
|
|
||||||
<mimeMap fileExtension=".accde" mimeType="application/msaccess" />
|
|
||||||
<mimeMap fileExtension=".accdt" mimeType="application/msaccess" />
|
|
||||||
<mimeMap fileExtension=".acx" mimeType="application/internet-property-stream" />
|
|
||||||
<mimeMap fileExtension=".adt" mimeType="audio/vnd.dlna.adts" />
|
|
||||||
<mimeMap fileExtension=".adts" mimeType="audio/vnd.dlna.adts" />
|
|
||||||
<mimeMap fileExtension=".afm" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".ai" mimeType="application/postscript" />
|
|
||||||
<mimeMap fileExtension=".aif" mimeType="audio/x-aiff" />
|
|
||||||
<mimeMap fileExtension=".aifc" mimeType="audio/aiff" />
|
|
||||||
<mimeMap fileExtension=".aiff" mimeType="audio/aiff" />
|
|
||||||
<mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" />
|
|
||||||
<mimeMap fileExtension=".application" mimeType="application/x-ms-application" />
|
|
||||||
<mimeMap fileExtension=".art" mimeType="image/x-jg" />
|
|
||||||
<mimeMap fileExtension=".asd" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".asf" mimeType="video/x-ms-asf" />
|
|
||||||
<mimeMap fileExtension=".asi" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".asm" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".asr" mimeType="video/x-ms-asf" />
|
|
||||||
<mimeMap fileExtension=".asx" mimeType="video/x-ms-asf" />
|
|
||||||
<mimeMap fileExtension=".atom" mimeType="application/atom+xml" />
|
|
||||||
<mimeMap fileExtension=".au" mimeType="audio/basic" />
|
|
||||||
<mimeMap fileExtension=".avi" mimeType="video/avi" />
|
|
||||||
<mimeMap fileExtension=".axs" mimeType="application/olescript" />
|
|
||||||
<mimeMap fileExtension=".bas" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".bcpio" mimeType="application/x-bcpio" />
|
|
||||||
<mimeMap fileExtension=".bin" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".bmp" mimeType="image/bmp" />
|
|
||||||
<mimeMap fileExtension=".c" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".cab" mimeType="application/vnd.ms-cab-compressed" />
|
|
||||||
<mimeMap fileExtension=".calx" mimeType="application/vnd.ms-office.calx" />
|
|
||||||
<mimeMap fileExtension=".cat" mimeType="application/vnd.ms-pki.seccat" />
|
|
||||||
<mimeMap fileExtension=".cdf" mimeType="application/x-cdf" />
|
|
||||||
<mimeMap fileExtension=".chm" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".class" mimeType="application/x-java-applet" />
|
|
||||||
<mimeMap fileExtension=".clp" mimeType="application/x-msclip" />
|
|
||||||
<mimeMap fileExtension=".cmx" mimeType="image/x-cmx" />
|
|
||||||
<mimeMap fileExtension=".cnf" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".cod" mimeType="image/cis-cod" />
|
|
||||||
<mimeMap fileExtension=".cpio" mimeType="application/x-cpio" />
|
|
||||||
<mimeMap fileExtension=".cpp" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".crd" mimeType="application/x-mscardfile" />
|
|
||||||
<mimeMap fileExtension=".crl" mimeType="application/pkix-crl" />
|
|
||||||
<mimeMap fileExtension=".crt" mimeType="application/x-x509-ca-cert" />
|
|
||||||
<mimeMap fileExtension=".csh" mimeType="application/x-csh" />
|
|
||||||
<mimeMap fileExtension=".css" mimeType="text/css" />
|
|
||||||
<mimeMap fileExtension=".csv" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".cur" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".dcr" mimeType="application/x-director" />
|
|
||||||
<mimeMap fileExtension=".deploy" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".der" mimeType="application/x-x509-ca-cert" />
|
|
||||||
<mimeMap fileExtension=".dib" mimeType="image/bmp" />
|
|
||||||
<mimeMap fileExtension=".dir" mimeType="application/x-director" />
|
|
||||||
<mimeMap fileExtension=".disco" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".dll" mimeType="application/x-msdownload" />
|
|
||||||
<mimeMap fileExtension=".dll.config" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".dlm" mimeType="text/dlm" />
|
|
||||||
<mimeMap fileExtension=".doc" mimeType="application/msword" />
|
|
||||||
<mimeMap fileExtension=".docm" mimeType="application/vnd.ms-word.document.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".docx" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
|
|
||||||
<mimeMap fileExtension=".dot" mimeType="application/msword" />
|
|
||||||
<mimeMap fileExtension=".dotm" mimeType="application/vnd.ms-word.template.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".dotx" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.template" />
|
|
||||||
<mimeMap fileExtension=".dsp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".dtd" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".dvi" mimeType="application/x-dvi" />
|
|
||||||
<mimeMap fileExtension=".dvr-ms" mimeType="video/x-ms-dvr" />
|
|
||||||
<mimeMap fileExtension=".dwf" mimeType="drawing/x-dwf" />
|
|
||||||
<mimeMap fileExtension=".dwp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".dxr" mimeType="application/x-director" />
|
|
||||||
<mimeMap fileExtension=".eml" mimeType="message/rfc822" />
|
|
||||||
<mimeMap fileExtension=".emz" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
|
|
||||||
<mimeMap fileExtension=".eps" mimeType="application/postscript" />
|
|
||||||
<mimeMap fileExtension=".esd" mimeType="application/vnd.ms-cab-compressed" />
|
|
||||||
<mimeMap fileExtension=".etx" mimeType="text/x-setext" />
|
|
||||||
<mimeMap fileExtension=".evy" mimeType="application/envoy" />
|
|
||||||
<mimeMap fileExtension=".exe" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".exe.config" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".fdf" mimeType="application/vnd.fdf" />
|
|
||||||
<mimeMap fileExtension=".fif" mimeType="application/fractals" />
|
|
||||||
<mimeMap fileExtension=".fla" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".flr" mimeType="x-world/x-vrml" />
|
|
||||||
<mimeMap fileExtension=".flv" mimeType="video/x-flv" />
|
|
||||||
<mimeMap fileExtension=".gif" mimeType="image/gif" />
|
|
||||||
<mimeMap fileExtension=".glb" mimeType="model/gltf-binary" />
|
|
||||||
<mimeMap fileExtension=".gtar" mimeType="application/x-gtar" />
|
|
||||||
<mimeMap fileExtension=".gz" mimeType="application/x-gzip" />
|
|
||||||
<mimeMap fileExtension=".h" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".hdf" mimeType="application/x-hdf" />
|
|
||||||
<mimeMap fileExtension=".hdml" mimeType="text/x-hdml" />
|
|
||||||
<mimeMap fileExtension=".hhc" mimeType="application/x-oleobject" />
|
|
||||||
<mimeMap fileExtension=".hhk" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".hhp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".hlp" mimeType="application/winhlp" />
|
|
||||||
<mimeMap fileExtension=".hqx" mimeType="application/mac-binhex40" />
|
|
||||||
<mimeMap fileExtension=".hta" mimeType="application/hta" />
|
|
||||||
<mimeMap fileExtension=".htc" mimeType="text/x-component" />
|
|
||||||
<mimeMap fileExtension=".htm" mimeType="text/html" />
|
|
||||||
<mimeMap fileExtension=".html" mimeType="text/html" />
|
|
||||||
<mimeMap fileExtension=".htt" mimeType="text/webviewhtml" />
|
|
||||||
<mimeMap fileExtension=".hxt" mimeType="text/html" />
|
|
||||||
<mimeMap fileExtension=".ico" mimeType="image/x-icon" />
|
|
||||||
<mimeMap fileExtension=".ics" mimeType="text/calendar" />
|
|
||||||
<mimeMap fileExtension=".ief" mimeType="image/ief" />
|
|
||||||
<mimeMap fileExtension=".iii" mimeType="application/x-iphone" />
|
|
||||||
<mimeMap fileExtension=".inf" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".ins" mimeType="application/x-internet-signup" />
|
|
||||||
<mimeMap fileExtension=".isp" mimeType="application/x-internet-signup" />
|
|
||||||
<mimeMap fileExtension=".IVF" mimeType="video/x-ivf" />
|
|
||||||
<mimeMap fileExtension=".jar" mimeType="application/java-archive" />
|
|
||||||
<mimeMap fileExtension=".java" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".jck" mimeType="application/liquidmotion" />
|
|
||||||
<mimeMap fileExtension=".jcz" mimeType="application/liquidmotion" />
|
|
||||||
<mimeMap fileExtension=".jfif" mimeType="image/pjpeg" />
|
|
||||||
<mimeMap fileExtension=".jpb" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".jpe" mimeType="image/jpeg" />
|
|
||||||
<mimeMap fileExtension=".jpeg" mimeType="image/jpeg" />
|
|
||||||
<mimeMap fileExtension=".jpg" mimeType="image/jpeg" />
|
|
||||||
<mimeMap fileExtension=".js" mimeType="application/javascript" />
|
|
||||||
<mimeMap fileExtension=".json" mimeType="application/json" />
|
|
||||||
<mimeMap fileExtension=".jsonld" mimeType="application/ld+json" />
|
|
||||||
<mimeMap fileExtension=".jsx" mimeType="text/jscript" />
|
|
||||||
<mimeMap fileExtension=".latex" mimeType="application/x-latex" />
|
|
||||||
<mimeMap fileExtension=".less" mimeType="text/css" />
|
|
||||||
<mimeMap fileExtension=".lit" mimeType="application/x-ms-reader" />
|
|
||||||
<mimeMap fileExtension=".lpk" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".lsf" mimeType="video/x-la-asf" />
|
|
||||||
<mimeMap fileExtension=".lsx" mimeType="video/x-la-asf" />
|
|
||||||
<mimeMap fileExtension=".lzh" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".m13" mimeType="application/x-msmediaview" />
|
|
||||||
<mimeMap fileExtension=".m14" mimeType="application/x-msmediaview" />
|
|
||||||
<mimeMap fileExtension=".m1v" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".m2ts" mimeType="video/vnd.dlna.mpeg-tts" />
|
|
||||||
<mimeMap fileExtension=".m3u" mimeType="audio/x-mpegurl" />
|
|
||||||
<mimeMap fileExtension=".m4a" mimeType="audio/mp4" />
|
|
||||||
<mimeMap fileExtension=".m4v" mimeType="video/mp4" />
|
|
||||||
<mimeMap fileExtension=".man" mimeType="application/x-troff-man" />
|
|
||||||
<mimeMap fileExtension=".manifest" mimeType="application/x-ms-manifest" />
|
|
||||||
<mimeMap fileExtension=".map" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".mdb" mimeType="application/x-msaccess" />
|
|
||||||
<mimeMap fileExtension=".mdp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".me" mimeType="application/x-troff-me" />
|
|
||||||
<mimeMap fileExtension=".mht" mimeType="message/rfc822" />
|
|
||||||
<mimeMap fileExtension=".mhtml" mimeType="message/rfc822" />
|
|
||||||
<mimeMap fileExtension=".mid" mimeType="audio/mid" />
|
|
||||||
<mimeMap fileExtension=".midi" mimeType="audio/mid" />
|
|
||||||
<mimeMap fileExtension=".mix" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".mmf" mimeType="application/x-smaf" />
|
|
||||||
<mimeMap fileExtension=".mno" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".mny" mimeType="application/x-msmoney" />
|
|
||||||
<mimeMap fileExtension=".mov" mimeType="video/quicktime" />
|
|
||||||
<mimeMap fileExtension=".movie" mimeType="video/x-sgi-movie" />
|
|
||||||
<mimeMap fileExtension=".mp2" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".mp3" mimeType="audio/mpeg" />
|
|
||||||
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
|
|
||||||
<mimeMap fileExtension=".mp4v" mimeType="video/mp4" />
|
|
||||||
<mimeMap fileExtension=".mpa" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".mpe" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".mpeg" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".mpg" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".mpp" mimeType="application/vnd.ms-project" />
|
|
||||||
<mimeMap fileExtension=".mpv2" mimeType="video/mpeg" />
|
|
||||||
<mimeMap fileExtension=".ms" mimeType="application/x-troff-ms" />
|
|
||||||
<mimeMap fileExtension=".msi" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".mso" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".mvb" mimeType="application/x-msmediaview" />
|
|
||||||
<mimeMap fileExtension=".mvc" mimeType="application/x-miva-compiled" />
|
|
||||||
<mimeMap fileExtension=".nc" mimeType="application/x-netcdf" />
|
|
||||||
<mimeMap fileExtension=".nsc" mimeType="video/x-ms-asf" />
|
|
||||||
<mimeMap fileExtension=".nws" mimeType="message/rfc822" />
|
|
||||||
<mimeMap fileExtension=".ocx" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".oda" mimeType="application/oda" />
|
|
||||||
<mimeMap fileExtension=".odc" mimeType="text/x-ms-odc" />
|
|
||||||
<mimeMap fileExtension=".ods" mimeType="application/oleobject" />
|
|
||||||
<mimeMap fileExtension=".oga" mimeType="audio/ogg" />
|
|
||||||
<mimeMap fileExtension=".ogg" mimeType="video/ogg" />
|
|
||||||
<mimeMap fileExtension=".ogv" mimeType="video/ogg" />
|
|
||||||
<mimeMap fileExtension=".one" mimeType="application/onenote" />
|
|
||||||
<mimeMap fileExtension=".onea" mimeType="application/onenote" />
|
|
||||||
<mimeMap fileExtension=".onetoc" mimeType="application/onenote" />
|
|
||||||
<mimeMap fileExtension=".onetoc2" mimeType="application/onenote" />
|
|
||||||
<mimeMap fileExtension=".onetmp" mimeType="application/onenote" />
|
|
||||||
<mimeMap fileExtension=".onepkg" mimeType="application/onenote" />
|
|
||||||
<mimeMap fileExtension=".osdx" mimeType="application/opensearchdescription+xml" />
|
|
||||||
<mimeMap fileExtension=".otf" mimeType="font/otf" />
|
|
||||||
<mimeMap fileExtension=".p10" mimeType="application/pkcs10" />
|
|
||||||
<mimeMap fileExtension=".p12" mimeType="application/x-pkcs12" />
|
|
||||||
<mimeMap fileExtension=".p7b" mimeType="application/x-pkcs7-certificates" />
|
|
||||||
<mimeMap fileExtension=".p7c" mimeType="application/pkcs7-mime" />
|
|
||||||
<mimeMap fileExtension=".p7m" mimeType="application/pkcs7-mime" />
|
|
||||||
<mimeMap fileExtension=".p7r" mimeType="application/x-pkcs7-certreqresp" />
|
|
||||||
<mimeMap fileExtension=".p7s" mimeType="application/pkcs7-signature" />
|
|
||||||
<mimeMap fileExtension=".pbm" mimeType="image/x-portable-bitmap" />
|
|
||||||
<mimeMap fileExtension=".pcx" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".pcz" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".pdf" mimeType="application/pdf" />
|
|
||||||
<mimeMap fileExtension=".pfb" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".pfm" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".pfx" mimeType="application/x-pkcs12" />
|
|
||||||
<mimeMap fileExtension=".pgm" mimeType="image/x-portable-graymap" />
|
|
||||||
<mimeMap fileExtension=".pko" mimeType="application/vnd.ms-pki.pko" />
|
|
||||||
<mimeMap fileExtension=".pma" mimeType="application/x-perfmon" />
|
|
||||||
<mimeMap fileExtension=".pmc" mimeType="application/x-perfmon" />
|
|
||||||
<mimeMap fileExtension=".pml" mimeType="application/x-perfmon" />
|
|
||||||
<mimeMap fileExtension=".pmr" mimeType="application/x-perfmon" />
|
|
||||||
<mimeMap fileExtension=".pmw" mimeType="application/x-perfmon" />
|
|
||||||
<mimeMap fileExtension=".png" mimeType="image/png" />
|
|
||||||
<mimeMap fileExtension=".pnm" mimeType="image/x-portable-anymap" />
|
|
||||||
<mimeMap fileExtension=".pnz" mimeType="image/png" />
|
|
||||||
<mimeMap fileExtension=".pot" mimeType="application/vnd.ms-powerpoint" />
|
|
||||||
<mimeMap fileExtension=".potm" mimeType="application/vnd.ms-powerpoint.template.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".potx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.template" />
|
|
||||||
<mimeMap fileExtension=".ppam" mimeType="application/vnd.ms-powerpoint.addin.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".ppm" mimeType="image/x-portable-pixmap" />
|
|
||||||
<mimeMap fileExtension=".pps" mimeType="application/vnd.ms-powerpoint" />
|
|
||||||
<mimeMap fileExtension=".ppsm" mimeType="application/vnd.ms-powerpoint.slideshow.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".ppsx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.slideshow" />
|
|
||||||
<mimeMap fileExtension=".ppt" mimeType="application/vnd.ms-powerpoint" />
|
|
||||||
<mimeMap fileExtension=".pptm" mimeType="application/vnd.ms-powerpoint.presentation.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".pptx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
|
|
||||||
<mimeMap fileExtension=".prf" mimeType="application/pics-rules" />
|
|
||||||
<mimeMap fileExtension=".prm" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".prx" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".ps" mimeType="application/postscript" />
|
|
||||||
<mimeMap fileExtension=".psd" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".psm" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".psp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".pub" mimeType="application/x-mspublisher" />
|
|
||||||
<mimeMap fileExtension=".qt" mimeType="video/quicktime" />
|
|
||||||
<mimeMap fileExtension=".qtl" mimeType="application/x-quicktimeplayer" />
|
|
||||||
<mimeMap fileExtension=".qxd" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".ra" mimeType="audio/x-pn-realaudio" />
|
|
||||||
<mimeMap fileExtension=".ram" mimeType="audio/x-pn-realaudio" />
|
|
||||||
<mimeMap fileExtension=".rar" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".ras" mimeType="image/x-cmu-raster" />
|
|
||||||
<mimeMap fileExtension=".rf" mimeType="image/vnd.rn-realflash" />
|
|
||||||
<mimeMap fileExtension=".rgb" mimeType="image/x-rgb" />
|
|
||||||
<mimeMap fileExtension=".rm" mimeType="application/vnd.rn-realmedia" />
|
|
||||||
<mimeMap fileExtension=".rmi" mimeType="audio/mid" />
|
|
||||||
<mimeMap fileExtension=".roff" mimeType="application/x-troff" />
|
|
||||||
<mimeMap fileExtension=".rpm" mimeType="audio/x-pn-realaudio-plugin" />
|
|
||||||
<mimeMap fileExtension=".rtf" mimeType="application/rtf" />
|
|
||||||
<mimeMap fileExtension=".rtx" mimeType="text/richtext" />
|
|
||||||
<mimeMap fileExtension=".scd" mimeType="application/x-msschedule" />
|
|
||||||
<mimeMap fileExtension=".sct" mimeType="text/scriptlet" />
|
|
||||||
<mimeMap fileExtension=".sea" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".setpay" mimeType="application/set-payment-initiation" />
|
|
||||||
<mimeMap fileExtension=".setreg" mimeType="application/set-registration-initiation" />
|
|
||||||
<mimeMap fileExtension=".sgml" mimeType="text/sgml" />
|
|
||||||
<mimeMap fileExtension=".sh" mimeType="application/x-sh" />
|
|
||||||
<mimeMap fileExtension=".shar" mimeType="application/x-shar" />
|
|
||||||
<mimeMap fileExtension=".sit" mimeType="application/x-stuffit" />
|
|
||||||
<mimeMap fileExtension=".sldm" mimeType="application/vnd.ms-powerpoint.slide.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".sldx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.slide" />
|
|
||||||
<mimeMap fileExtension=".smd" mimeType="audio/x-smd" />
|
|
||||||
<mimeMap fileExtension=".smi" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".smx" mimeType="audio/x-smd" />
|
|
||||||
<mimeMap fileExtension=".smz" mimeType="audio/x-smd" />
|
|
||||||
<mimeMap fileExtension=".snd" mimeType="audio/basic" />
|
|
||||||
<mimeMap fileExtension=".snp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".spc" mimeType="application/x-pkcs7-certificates" />
|
|
||||||
<mimeMap fileExtension=".spl" mimeType="application/futuresplash" />
|
|
||||||
<mimeMap fileExtension=".spx" mimeType="audio/ogg" />
|
|
||||||
<mimeMap fileExtension=".src" mimeType="application/x-wais-source" />
|
|
||||||
<mimeMap fileExtension=".ssm" mimeType="application/streamingmedia" />
|
|
||||||
<mimeMap fileExtension=".sst" mimeType="application/vnd.ms-pki.certstore" />
|
|
||||||
<mimeMap fileExtension=".stl" mimeType="application/vnd.ms-pki.stl" />
|
|
||||||
<mimeMap fileExtension=".sv4cpio" mimeType="application/x-sv4cpio" />
|
|
||||||
<mimeMap fileExtension=".sv4crc" mimeType="application/x-sv4crc" />
|
|
||||||
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
|
|
||||||
<mimeMap fileExtension=".svgz" mimeType="image/svg+xml" />
|
|
||||||
<mimeMap fileExtension=".swf" mimeType="application/x-shockwave-flash" />
|
|
||||||
<mimeMap fileExtension=".t" mimeType="application/x-troff" />
|
|
||||||
<mimeMap fileExtension=".tar" mimeType="application/x-tar" />
|
|
||||||
<mimeMap fileExtension=".tcl" mimeType="application/x-tcl" />
|
|
||||||
<mimeMap fileExtension=".tex" mimeType="application/x-tex" />
|
|
||||||
<mimeMap fileExtension=".texi" mimeType="application/x-texinfo" />
|
|
||||||
<mimeMap fileExtension=".texinfo" mimeType="application/x-texinfo" />
|
|
||||||
<mimeMap fileExtension=".tgz" mimeType="application/x-compressed" />
|
|
||||||
<mimeMap fileExtension=".thmx" mimeType="application/vnd.ms-officetheme" />
|
|
||||||
<mimeMap fileExtension=".thn" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".tif" mimeType="image/tiff" />
|
|
||||||
<mimeMap fileExtension=".tiff" mimeType="image/tiff" />
|
|
||||||
<mimeMap fileExtension=".toc" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".tr" mimeType="application/x-troff" />
|
|
||||||
<mimeMap fileExtension=".trm" mimeType="application/x-msterminal" />
|
|
||||||
<mimeMap fileExtension=".ts" mimeType="video/vnd.dlna.mpeg-tts" />
|
|
||||||
<mimeMap fileExtension=".tsv" mimeType="text/tab-separated-values" />
|
|
||||||
<mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".tts" mimeType="video/vnd.dlna.mpeg-tts" />
|
|
||||||
<mimeMap fileExtension=".txt" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".u32" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".uls" mimeType="text/iuls" />
|
|
||||||
<mimeMap fileExtension=".ustar" mimeType="application/x-ustar" />
|
|
||||||
<mimeMap fileExtension=".vbs" mimeType="text/vbscript" />
|
|
||||||
<mimeMap fileExtension=".vcf" mimeType="text/x-vcard" />
|
|
||||||
<mimeMap fileExtension=".vcs" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".vdx" mimeType="application/vnd.ms-visio.viewer" />
|
|
||||||
<mimeMap fileExtension=".vml" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".vsd" mimeType="application/vnd.visio" />
|
|
||||||
<mimeMap fileExtension=".vss" mimeType="application/vnd.visio" />
|
|
||||||
<mimeMap fileExtension=".vst" mimeType="application/vnd.visio" />
|
|
||||||
<mimeMap fileExtension=".vsto" mimeType="application/x-ms-vsto" />
|
|
||||||
<mimeMap fileExtension=".vsw" mimeType="application/vnd.visio" />
|
|
||||||
<mimeMap fileExtension=".vsx" mimeType="application/vnd.visio" />
|
|
||||||
<mimeMap fileExtension=".vtx" mimeType="application/vnd.visio" />
|
|
||||||
<mimeMap fileExtension=".wasm" mimeType="application/wasm" />
|
|
||||||
<mimeMap fileExtension=".wav" mimeType="audio/wav" />
|
|
||||||
<mimeMap fileExtension=".wax" mimeType="audio/x-ms-wax" />
|
|
||||||
<mimeMap fileExtension=".wbmp" mimeType="image/vnd.wap.wbmp" />
|
|
||||||
<mimeMap fileExtension=".wcm" mimeType="application/vnd.ms-works" />
|
|
||||||
<mimeMap fileExtension=".wdb" mimeType="application/vnd.ms-works" />
|
|
||||||
<mimeMap fileExtension=".webm" mimeType="video/webm" />
|
|
||||||
<mimeMap fileExtension=".wks" mimeType="application/vnd.ms-works" />
|
|
||||||
<mimeMap fileExtension=".wm" mimeType="video/x-ms-wm" />
|
|
||||||
<mimeMap fileExtension=".wma" mimeType="audio/x-ms-wma" />
|
|
||||||
<mimeMap fileExtension=".wmd" mimeType="application/x-ms-wmd" />
|
|
||||||
<mimeMap fileExtension=".wmf" mimeType="application/x-msmetafile" />
|
|
||||||
<mimeMap fileExtension=".wml" mimeType="text/vnd.wap.wml" />
|
|
||||||
<mimeMap fileExtension=".wmlc" mimeType="application/vnd.wap.wmlc" />
|
|
||||||
<mimeMap fileExtension=".wmls" mimeType="text/vnd.wap.wmlscript" />
|
|
||||||
<mimeMap fileExtension=".wmlsc" mimeType="application/vnd.wap.wmlscriptc" />
|
|
||||||
<mimeMap fileExtension=".wmp" mimeType="video/x-ms-wmp" />
|
|
||||||
<mimeMap fileExtension=".wmv" mimeType="video/x-ms-wmv" />
|
|
||||||
<mimeMap fileExtension=".wmx" mimeType="video/x-ms-wmx" />
|
|
||||||
<mimeMap fileExtension=".wmz" mimeType="application/x-ms-wmz" />
|
|
||||||
<mimeMap fileExtension=".woff" mimeType="font/x-woff" />
|
|
||||||
<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
|
|
||||||
<mimeMap fileExtension=".wps" mimeType="application/vnd.ms-works" />
|
|
||||||
<mimeMap fileExtension=".wri" mimeType="application/x-mswrite" />
|
|
||||||
<mimeMap fileExtension=".wrl" mimeType="x-world/x-vrml" />
|
|
||||||
<mimeMap fileExtension=".wrz" mimeType="x-world/x-vrml" />
|
|
||||||
<mimeMap fileExtension=".wsdl" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".wtv" mimeType="video/x-ms-wtv" />
|
|
||||||
<mimeMap fileExtension=".wvx" mimeType="video/x-ms-wvx" />
|
|
||||||
<mimeMap fileExtension=".x" mimeType="application/directx" />
|
|
||||||
<mimeMap fileExtension=".xaf" mimeType="x-world/x-vrml" />
|
|
||||||
<mimeMap fileExtension=".xaml" mimeType="application/xaml+xml" />
|
|
||||||
<mimeMap fileExtension=".xap" mimeType="application/x-silverlight-app" />
|
|
||||||
<mimeMap fileExtension=".xbap" mimeType="application/x-ms-xbap" />
|
|
||||||
<mimeMap fileExtension=".xbm" mimeType="image/x-xbitmap" />
|
|
||||||
<mimeMap fileExtension=".xdr" mimeType="text/plain" />
|
|
||||||
<mimeMap fileExtension=".xht" mimeType="application/xhtml+xml" />
|
|
||||||
<mimeMap fileExtension=".xhtml" mimeType="application/xhtml+xml" />
|
|
||||||
<mimeMap fileExtension=".xla" mimeType="application/vnd.ms-excel" />
|
|
||||||
<mimeMap fileExtension=".xlam" mimeType="application/vnd.ms-excel.addin.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".xlc" mimeType="application/vnd.ms-excel" />
|
|
||||||
<mimeMap fileExtension=".xlm" mimeType="application/vnd.ms-excel" />
|
|
||||||
<mimeMap fileExtension=".xls" mimeType="application/vnd.ms-excel" />
|
|
||||||
<mimeMap fileExtension=".xlsb" mimeType="application/vnd.ms-excel.sheet.binary.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".xlsm" mimeType="application/vnd.ms-excel.sheet.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".xlsx" mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
|
|
||||||
<mimeMap fileExtension=".xlt" mimeType="application/vnd.ms-excel" />
|
|
||||||
<mimeMap fileExtension=".xltm" mimeType="application/vnd.ms-excel.template.macroEnabled.12" />
|
|
||||||
<mimeMap fileExtension=".xltx" mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.template" />
|
|
||||||
<mimeMap fileExtension=".xlw" mimeType="application/vnd.ms-excel" />
|
|
||||||
<mimeMap fileExtension=".xml" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".xof" mimeType="x-world/x-vrml" />
|
|
||||||
<mimeMap fileExtension=".xpm" mimeType="image/x-xpixmap" />
|
|
||||||
<mimeMap fileExtension=".xps" mimeType="application/vnd.ms-xpsdocument" />
|
|
||||||
<mimeMap fileExtension=".xsd" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".xsf" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".xsl" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".xslt" mimeType="text/xml" />
|
|
||||||
<mimeMap fileExtension=".xsn" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".xtp" mimeType="application/octet-stream" />
|
|
||||||
<mimeMap fileExtension=".xwd" mimeType="image/x-xwindowdump" />
|
|
||||||
<mimeMap fileExtension=".z" mimeType="application/x-compress" />
|
|
||||||
<mimeMap fileExtension=".zip" mimeType="application/x-zip-compressed" />
|
|
||||||
</staticContent>
|
|
||||||
<tracing>
|
|
||||||
<traceFailedRequests>
|
|
||||||
<add path="*">
|
|
||||||
<traceAreas>
|
|
||||||
<add provider="ASP" verbosity="Verbose" />
|
|
||||||
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
|
|
||||||
<add provider="ISAPI Extension" verbosity="Verbose" />
|
|
||||||
<add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,Rewrite,WebSocket" verbosity="Verbose" />
|
|
||||||
</traceAreas>
|
|
||||||
<failureDefinitions statusCodes="200-999" />
|
|
||||||
</add>
|
|
||||||
</traceFailedRequests>
|
|
||||||
<traceProviderDefinitions>
|
|
||||||
<add name="WWW Server" guid="{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}">
|
|
||||||
<areas>
|
|
||||||
<clear />
|
|
||||||
<add name="Authentication" value="2" />
|
|
||||||
<add name="Security" value="4" />
|
|
||||||
<add name="Filter" value="8" />
|
|
||||||
<add name="StaticFile" value="16" />
|
|
||||||
<add name="CGI" value="32" />
|
|
||||||
<add name="Compression" value="64" />
|
|
||||||
<add name="Cache" value="128" />
|
|
||||||
<add name="RequestNotifications" value="256" />
|
|
||||||
<add name="Module" value="512" />
|
|
||||||
<add name="Rewrite" value="1024" />
|
|
||||||
<add name="FastCGI" value="4096" />
|
|
||||||
<add name="WebSocket" value="16384" />
|
|
||||||
</areas>
|
|
||||||
</add>
|
|
||||||
<add name="ASP" guid="{06b94d9a-b15e-456e-a4ef-37c984a2cb4b}">
|
|
||||||
<areas>
|
|
||||||
<clear />
|
|
||||||
</areas>
|
|
||||||
</add>
|
|
||||||
<add name="ISAPI Extension" guid="{a1c2040e-8840-4c31-ba11-9871031a19ea}">
|
|
||||||
<areas>
|
|
||||||
<clear />
|
|
||||||
</areas>
|
|
||||||
</add>
|
|
||||||
<add name="ASPNET" guid="{AFF081FE-0247-4275-9C4E-021F3DC1DA35}">
|
|
||||||
<areas>
|
|
||||||
<add name="Infrastructure" value="1" />
|
|
||||||
<add name="Module" value="2" />
|
|
||||||
<add name="Page" value="4" />
|
|
||||||
<add name="AppServices" value="8" />
|
|
||||||
</areas>
|
|
||||||
</add>
|
|
||||||
</traceProviderDefinitions>
|
|
||||||
</tracing>
|
|
||||||
<urlCompression />
|
|
||||||
<validation />
|
|
||||||
<webdav>
|
|
||||||
<globalSettings>
|
|
||||||
<propertyStores>
|
|
||||||
<add name="webdav_simple_prop" image="%IIS_BIN%\webdav_simple_prop.dll" image32="%IIS_BIN%\webdav_simple_prop.dll" />
|
|
||||||
</propertyStores>
|
|
||||||
<lockStores>
|
|
||||||
<add name="webdav_simple_lock" image="%IIS_BIN%\webdav_simple_lock.dll" image32="%IIS_BIN%\webdav_simple_lock.dll" />
|
|
||||||
</lockStores>
|
|
||||||
</globalSettings>
|
|
||||||
<authoring>
|
|
||||||
<locks enabled="true" lockStore="webdav_simple_lock" />
|
|
||||||
</authoring>
|
|
||||||
<authoringRules />
|
|
||||||
</webdav>
|
|
||||||
<webSocket />
|
|
||||||
<applicationInitialization />
|
|
||||||
</system.webServer>
|
|
||||||
<location path="" overrideMode="Allow">
|
|
||||||
<system.webServer>
|
|
||||||
<modules>
|
|
||||||
<add name="IsapiFilterModule" lockItem="true" />
|
|
||||||
<add name="BasicAuthenticationModule" lockItem="true" />
|
|
||||||
<add name="IsapiModule" lockItem="true" />
|
|
||||||
<add name="HttpLoggingModule" lockItem="true" />
|
|
||||||
<add name="DynamicCompressionModule" lockItem="true" />
|
|
||||||
<add name="StaticCompressionModule" lockItem="true" />
|
|
||||||
<add name="DefaultDocumentModule" lockItem="true" />
|
|
||||||
<add name="DirectoryListingModule" lockItem="true" />
|
|
||||||
<add name="ProtocolSupportModule" lockItem="true" />
|
|
||||||
<add name="HttpRedirectionModule" lockItem="true" />
|
|
||||||
<add name="ServerSideIncludeModule" lockItem="true" />
|
|
||||||
<add name="StaticFileModule" lockItem="true" />
|
|
||||||
<add name="AnonymousAuthenticationModule" lockItem="true" />
|
|
||||||
<add name="CertificateMappingAuthenticationModule" lockItem="true" />
|
|
||||||
<add name="UrlAuthorizationModule" lockItem="true" />
|
|
||||||
<add name="WindowsAuthenticationModule" lockItem="true" />
|
|
||||||
<add name="IISCertificateMappingAuthenticationModule" lockItem="true" />
|
|
||||||
<add name="WebMatrixSupportModule" lockItem="true" />
|
|
||||||
<add name="IpRestrictionModule" lockItem="true" />
|
|
||||||
<add name="DynamicIpRestrictionModule" lockItem="true" />
|
|
||||||
<add name="RequestFilteringModule" lockItem="true" />
|
|
||||||
<add name="CustomLoggingModule" lockItem="true" />
|
|
||||||
<add name="CustomErrorModule" lockItem="true" />
|
|
||||||
<add name="FailedRequestsTracingModule" lockItem="true" />
|
|
||||||
<add name="CgiModule" lockItem="true" />
|
|
||||||
<add name="FastCgiModule" lockItem="true" />
|
|
||||||
<!-- <add name="WebDAVModule" /> -->
|
|
||||||
<add name="RewriteModule" />
|
|
||||||
<add name="OutputCache" type="System.Web.Caching.OutputCacheModule" preCondition="managedHandler" />
|
|
||||||
<add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition="managedHandler" />
|
|
||||||
<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" preCondition="managedHandler" />
|
|
||||||
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="managedHandler" />
|
|
||||||
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="managedHandler" />
|
|
||||||
<add name="RoleManager" type="System.Web.Security.RoleManagerModule" preCondition="managedHandler" />
|
|
||||||
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />
|
|
||||||
<add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" preCondition="managedHandler" />
|
|
||||||
<add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" preCondition="managedHandler" />
|
|
||||||
<add name="Profile" type="System.Web.Profile.ProfileModule" preCondition="managedHandler" />
|
|
||||||
<add name="UrlMappingsModule" type="System.Web.UrlMappingsModule" preCondition="managedHandler" />
|
|
||||||
<add name="ApplicationInitializationModule" lockItem="true" />
|
|
||||||
<add name="WebSocketModule" lockItem="true" />
|
|
||||||
<add name="ServiceModel-4.0" type="System.ServiceModel.Activation.ServiceHttpModule,System.ServiceModel.Activation,Version=4.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
|
|
||||||
<add name="ConfigurationValidationModule" lockItem="true" />
|
|
||||||
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
|
|
||||||
<add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
|
|
||||||
<add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler,runtimeVersionv2.0" />
|
|
||||||
<add name="AspNetCoreModuleV2" />
|
|
||||||
</modules>
|
|
||||||
<handlers accessPolicy="Read, Script">
|
|
||||||
<!-- <add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" /> -->
|
|
||||||
<add name="AXD-ISAPI-4.0_64bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="PageHandlerFactory-ISAPI-4.0_64bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="SimpleHandlerFactory-ISAPI-4.0_64bit" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="WebServiceHandlerFactory-ISAPI-4.0_64bit" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-rem-ISAPI-4.0_64bit" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-soap-ISAPI-4.0_64bit" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="svc-ISAPI-4.0_64bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
|
|
||||||
<add name="rules-ISAPI-4.0_64bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
|
|
||||||
<add name="xoml-ISAPI-4.0_64bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
|
|
||||||
<add name="xamlx-ISAPI-4.0_64bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
|
|
||||||
<add name="aspq-ISAPI-4.0_64bit" path="*.aspq" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="cshtm-ISAPI-4.0_64bit" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="cshtml-ISAPI-4.0_64bit" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="vbhtm-ISAPI-4.0_64bit" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="vbhtml-ISAPI-4.0_64bit" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="svc-Integrated" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="svc-ISAPI-2.0" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
|
|
||||||
<add name="xoml-Integrated" path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="xoml-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
|
|
||||||
<add name="rules-Integrated" path="*.rules" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="rules-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
|
|
||||||
<add name="AXD-ISAPI-4.0_32bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="PageHandlerFactory-ISAPI-4.0_32bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="SimpleHandlerFactory-ISAPI-4.0_32bit" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="WebServiceHandlerFactory-ISAPI-4.0_32bit" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-rem-ISAPI-4.0_32bit" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-soap-ISAPI-4.0_32bit" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="svc-ISAPI-4.0_32bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
|
|
||||||
<add name="rules-ISAPI-4.0_32bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
|
|
||||||
<add name="xoml-ISAPI-4.0_32bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
|
|
||||||
<add name="xamlx-ISAPI-4.0_32bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
|
|
||||||
<add name="aspq-ISAPI-4.0_32bit" path="*.aspq" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="cshtm-ISAPI-4.0_32bit" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="cshtml-ISAPI-4.0_32bit" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="vbhtm-ISAPI-4.0_32bit" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="vbhtml-ISAPI-4.0_32bit" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="TraceHandler-Integrated-4.0" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="WebAdminHandler-Integrated-4.0" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="AssemblyResourceLoader-Integrated-4.0" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="WebServiceHandlerFactory-Integrated-4.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-rem-Integrated-4.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-soap-Integrated-4.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="svc-Integrated-4.0" path="*.svc" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="rules-Integrated-4.0" path="*.rules" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="xoml-Integrated-4.0" path="*.xoml" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="xamlx-Integrated-4.0" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="aspq-Integrated-4.0" path="*.aspq" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="cshtm-Integrated-4.0" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="cshtml-Integrated-4.0" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="vbhtm-Integrated-4.0" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="vbhtml-Integrated-4.0" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="ScriptHandlerFactoryAppServices-Integrated-4.0" path="*_AppService.axd" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="ScriptResourceIntegrated-4.0" path="*ScriptResource.axd" verb="GET,HEAD" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv4.0" />
|
|
||||||
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%IIS_BIN%\asp.dll" resourceType="File" />
|
|
||||||
<add name="SecurityCertificate" path="*.cer" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%IIS_BIN%\asp.dll" resourceType="File" />
|
|
||||||
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
|
|
||||||
<add name="TraceHandler-Integrated" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="WebAdminHandler-Integrated" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="AssemblyResourceLoader-Integrated" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="WebServiceHandlerFactory-Integrated" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Services.Protocols.WebServiceHandlerFactory,System.Web.Services,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-rem-Integrated" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-soap-Integrated" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
|
|
||||||
<add name="AXD-ISAPI-2.0" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="WebServiceHandlerFactory-ISAPI-2.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="svc-ISAPI-2.0-64" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
|
|
||||||
<add name="AXD-ISAPI-2.0-64" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="PageHandlerFactory-ISAPI-2.0-64" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="SimpleHandlerFactory-ISAPI-2.0-64" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="WebServiceHandlerFactory-ISAPI-2.0-64" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0-64" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0-64" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="rules-64-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
|
|
||||||
<add name="xoml-64-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
|
|
||||||
<add name="CGI-exe" path="*.exe" verb="*" modules="CgiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
|
|
||||||
<add name="SSINC-stm" path="*.stm" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" />
|
|
||||||
<add name="SSINC-shtm" path="*.shtm" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" />
|
|
||||||
<add name="SSINC-shtml" path="*.shtml" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" />
|
|
||||||
<add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" />
|
|
||||||
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
|
|
||||||
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
|
||||||
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
|
||||||
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
|
|
||||||
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
|
|
||||||
</handlers>
|
|
||||||
</system.webServer>
|
|
||||||
</location>
|
|
||||||
<location path="GreenHome.Api" inheritInChildApplications="false">
|
|
||||||
<system.webServer>
|
|
||||||
<modules>
|
|
||||||
<remove name="WebMatrixSupportModule" />
|
|
||||||
</modules>
|
|
||||||
<handlers>
|
|
||||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
|
||||||
</handlers>
|
|
||||||
<aspNetCore processPath="%LAUNCHER_PATH%" stdoutLogEnabled="false" hostingModel="InProcess" startupTimeLimit="3600" requestTimeout="23:00:00" />
|
|
||||||
<httpCompression>
|
|
||||||
<dynamicTypes>
|
|
||||||
<add mimeType="text/event-stream" enabled="false" />
|
|
||||||
</dynamicTypes>
|
|
||||||
</httpCompression>
|
|
||||||
</system.webServer>
|
|
||||||
</location>
|
|
||||||
</configuration>
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,217 +0,0 @@
|
|||||||
{
|
|
||||||
"Version": 1,
|
|
||||||
"WorkspaceRootPath": "D:\\Data\\Projects\\php\\greenhome\\src\\",
|
|
||||||
"Documents": [
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\docker-compose.yaml||{8B382828-6202-11D1-8870-0000F87579D2}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\docker-compose.yaml||{8B382828-6202-11D1-8870-0000F87579D2}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\dockerfile||{8B382828-6202-11D1-8870-0000F87579D2}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\dockerfile||{8B382828-6202-11D1-8870-0000F87579D2}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\controllers\\devicescontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\controllers\\devicescontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.application\\ideviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|solutionrelative:greenhome.application\\ideviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.infrastructure\\deviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|solutionrelative:greenhome.infrastructure\\deviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.infrastructure\\devicesettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|solutionrelative:greenhome.infrastructure\\devicesettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{31D70B40-BD35-4DA8-8E2B-B51120C85F19}|GreenHome.Domain\\GreenHome.Domain.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.domain\\devicesettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{31D70B40-BD35-4DA8-8E2B-B51120C85F19}|GreenHome.Domain\\GreenHome.Domain.csproj|solutionrelative:greenhome.domain\\devicesettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.application\\dtos.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|solutionrelative:greenhome.application\\dtos.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\controllers\\devicesettingscontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\controllers\\devicesettingscontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.infrastructure\\migrations\\20251008205106_addminmaxdanger.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|solutionrelative:greenhome.infrastructure\\migrations\\20251008205106_addminmaxdanger.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"DocumentGroupContainers": [
|
|
||||||
{
|
|
||||||
"Orientation": 0,
|
|
||||||
"VerticalTabListWidth": 256,
|
|
||||||
"DocumentGroups": [
|
|
||||||
{
|
|
||||||
"DockedWidth": 200,
|
|
||||||
"SelectedChildIndex": 6,
|
|
||||||
"Children": [
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 1,
|
|
||||||
"Title": "appsettings.json",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\appsettings.json",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\appsettings.json",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\appsettings.json",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\appsettings.json",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAADAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
|
|
||||||
"WhenOpened": "2025-10-27T09:37:37.683Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 3,
|
|
||||||
"Title": "Dockerfile",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Dockerfile",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Dockerfile",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Dockerfile",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Dockerfile",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
|
||||||
"WhenOpened": "2025-10-27T09:01:10.154Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 2,
|
|
||||||
"Title": "docker-compose.yaml",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"ViewState": "AgIAAAYAAAAAAAAAAAAAABgAAAA8AAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003775|",
|
|
||||||
"WhenOpened": "2025-10-27T08:53:42.956Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 5,
|
|
||||||
"Title": "IDeviceService.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-24T20:02:14.809Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 6,
|
|
||||||
"Title": "DeviceService.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"ViewState": "AgIAABEAAAAAAAAAAAA/wB8AAAA+AAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-24T20:05:51.455Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 10,
|
|
||||||
"Title": "DeviceSettingsController.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-24T19:57:36.263Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 0,
|
|
||||||
"Title": "Program.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Program.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Program.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Program.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Program.cs",
|
|
||||||
"ViewState": "AgIAAAQAAAAAAAAAAAAAABcAAAAWAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T21:01:05.32Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 7,
|
|
||||||
"Title": "DeviceSettingsService.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"ViewState": "AgIAAAkAAAAAAAAAAAAAwBsAAAAvAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T19:54:46.503Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 4,
|
|
||||||
"Title": "DevicesController.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"ViewState": "AgIAAA0AAAAAAAAAAAAnwBcAAAAZAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T19:34:42.977Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 11,
|
|
||||||
"Title": "20251008205106_addminmaxdanger.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAJAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-08T20:51:06.838Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 9,
|
|
||||||
"Title": "Dtos.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\Dtos.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Application\\Dtos.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\Dtos.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Application\\Dtos.cs",
|
|
||||||
"ViewState": "AgIAACwAAAAAAAAAAAAowDAAAAAjAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T17:00:06.672Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 8,
|
|
||||||
"Title": "DeviceSettings.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T16:59:47.282Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
{
|
|
||||||
"Version": 1,
|
|
||||||
"WorkspaceRootPath": "D:\\Data\\Projects\\php\\greenhome\\src\\",
|
|
||||||
"Documents": [
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.application\\dtos.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|solutionrelative:greenhome.application\\dtos.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\appsettings.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\docker-compose.yaml||{8B382828-6202-11D1-8870-0000F87579D2}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\docker-compose.yaml||{8B382828-6202-11D1-8870-0000F87579D2}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\dockerfile||{8B382828-6202-11D1-8870-0000F87579D2}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\dockerfile||{8B382828-6202-11D1-8870-0000F87579D2}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\controllers\\devicescontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\controllers\\devicescontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.application\\ideviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{4E330D53-37E7-42D3-B38C-E0DDF52CEA35}|GreenHome.Application\\GreenHome.Application.csproj|solutionrelative:greenhome.application\\ideviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.infrastructure\\deviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|solutionrelative:greenhome.infrastructure\\deviceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.infrastructure\\devicesettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|solutionrelative:greenhome.infrastructure\\devicesettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{31D70B40-BD35-4DA8-8E2B-B51120C85F19}|GreenHome.Domain\\GreenHome.Domain.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.domain\\devicesettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{31D70B40-BD35-4DA8-8E2B-B51120C85F19}|GreenHome.Domain\\GreenHome.Domain.csproj|solutionrelative:greenhome.domain\\devicesettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.api\\controllers\\devicesettingscontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{75E498D4-5D04-4F63-A1A5-5D851FA40C74}|GreenHome.Api\\GreenHome.Api.csproj|solutionrelative:greenhome.api\\controllers\\devicesettingscontroller.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AbsoluteMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|d:\\data\\projects\\php\\greenhome\\src\\greenhome.infrastructure\\migrations\\20251008205106_addminmaxdanger.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
|
||||||
"RelativeMoniker": "D:0:0:{D41BC2ED-CB72-4A98-82D6-8B6B7EC9423C}|GreenHome.Infrastructure\\GreenHome.Infrastructure.csproj|solutionrelative:greenhome.infrastructure\\migrations\\20251008205106_addminmaxdanger.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"DocumentGroupContainers": [
|
|
||||||
{
|
|
||||||
"Orientation": 0,
|
|
||||||
"VerticalTabListWidth": 256,
|
|
||||||
"DocumentGroups": [
|
|
||||||
{
|
|
||||||
"DockedWidth": 200,
|
|
||||||
"SelectedChildIndex": 5,
|
|
||||||
"Children": [
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 2,
|
|
||||||
"Title": "appsettings.json",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\appsettings.json",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\appsettings.json",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\appsettings.json",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\appsettings.json",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAADAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
|
|
||||||
"WhenOpened": "2025-10-27T09:37:37.683Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 4,
|
|
||||||
"Title": "Dockerfile",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Dockerfile",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Dockerfile",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Dockerfile",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Dockerfile",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
|
||||||
"WhenOpened": "2025-10-27T09:01:10.154Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 3,
|
|
||||||
"Title": "docker-compose.yaml",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\docker-compose.yaml",
|
|
||||||
"ViewState": "AgIAAAYAAAAAAAAAAAAAABgAAAA8AAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003775|",
|
|
||||||
"WhenOpened": "2025-10-27T08:53:42.956Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 7,
|
|
||||||
"Title": "DeviceService.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Infrastructure\\DeviceService.cs",
|
|
||||||
"ViewState": "AgIAABEAAAAAAAAAAAA/wB8AAAA+AAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-24T20:05:51.455Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 10,
|
|
||||||
"Title": "DeviceSettingsController.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Controllers\\DeviceSettingsController.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-24T19:57:36.263Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 0,
|
|
||||||
"Title": "Dtos.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\Dtos.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Application\\Dtos.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\Dtos.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Application\\Dtos.cs",
|
|
||||||
"ViewState": "AgIAACwAAAAAAAAAAAA7wDMAAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T17:00:06.672Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 6,
|
|
||||||
"Title": "IDeviceService.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Application\\IDeviceService.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAABAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-24T20:02:14.809Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 1,
|
|
||||||
"Title": "Program.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Program.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Program.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Program.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Program.cs",
|
|
||||||
"ViewState": "AgIAAAQAAAAAAAAAAAAAABcAAAAWAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T21:01:05.32Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 8,
|
|
||||||
"Title": "DeviceSettingsService.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Infrastructure\\DeviceSettingsService.cs",
|
|
||||||
"ViewState": "AgIAAAkAAAAAAAAAAAAAwBsAAAAvAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T19:54:46.503Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 5,
|
|
||||||
"Title": "DevicesController.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Api\\Controllers\\DevicesController.cs",
|
|
||||||
"ViewState": "AgIAAA0AAAAAAAAAAAAnwBcAAAAZAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T19:34:42.977Z",
|
|
||||||
"EditorCaption": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 11,
|
|
||||||
"Title": "20251008205106_addminmaxdanger.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Infrastructure\\Migrations\\20251008205106_addminmaxdanger.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAJAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-08T20:51:06.838Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$type": "Document",
|
|
||||||
"DocumentIndex": 9,
|
|
||||||
"Title": "DeviceSettings.cs",
|
|
||||||
"DocumentMoniker": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"RelativeDocumentMoniker": "GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"ToolTip": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"RelativeToolTip": "GreenHome.Domain\\DeviceSettings.cs",
|
|
||||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA==",
|
|
||||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
|
||||||
"WhenOpened": "2025-10-05T16:59:47.282Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
353
src/AI_QUERY_TRACKING.md
Normal file
353
src/AI_QUERY_TRACKING.md
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
# 📊 سیستم ذخیره و ردیابی سوالات هوش مصنوعی
|
||||||
|
|
||||||
|
## ✅ قابلیتهای اضافه شده
|
||||||
|
|
||||||
|
### 1. ذخیره خودکار سوالات و پاسخها
|
||||||
|
تمام سوالاتی که به AI ارسال میشود و پاسخهای دریافتی، به صورت خودکار در دیتابیس ذخیره میشوند.
|
||||||
|
|
||||||
|
### 2. ردیابی مصرف توکن
|
||||||
|
برای هر سوال، اطلاعات کامل توکن ذخیره میشود:
|
||||||
|
- **PromptTokens**: تعداد توکنهای سوال
|
||||||
|
- **CompletionTokens**: تعداد توکنهای پاسخ
|
||||||
|
- **TotalTokens**: مجموع توکنهای استفاده شده
|
||||||
|
|
||||||
|
### 3. ارتباط با دستگاه
|
||||||
|
هر سوال میتواند به یک دستگاه خاص مرتبط شود (با ارسال `deviceId`)
|
||||||
|
|
||||||
|
### 4. ارتباط با کاربر
|
||||||
|
هر سوال میتواند به یک کاربر خاص مرتبط شود (با ارسال `userId`)
|
||||||
|
|
||||||
|
### 5. اندازهگیری زمان پاسخ
|
||||||
|
زمان پاسخدهی به میلیثانیه اندازهگیری و ذخیره میشود
|
||||||
|
|
||||||
|
## 📋 جدول دیتابیس: AIQueries
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE AIQueries (
|
||||||
|
Id INT PRIMARY KEY IDENTITY,
|
||||||
|
DeviceId INT NULL, -- شماره دستگاه (اختیاری)
|
||||||
|
UserId INT NULL, -- شماره کاربر (اختیاری)
|
||||||
|
Question NVARCHAR(MAX) NOT NULL, -- سوال
|
||||||
|
Answer NVARCHAR(MAX) NOT NULL, -- پاسخ
|
||||||
|
PromptTokens INT NOT NULL, -- توکنهای سوال
|
||||||
|
CompletionTokens INT NOT NULL, -- توکنهای پاسخ
|
||||||
|
TotalTokens INT NOT NULL, -- مجموع توکنها
|
||||||
|
Model NVARCHAR(100) NULL, -- مدل استفاده شده
|
||||||
|
Temperature FLOAT NULL, -- پارامتر Temperature
|
||||||
|
ResponseTimeMs BIGINT NULL, -- زمان پاسخ (میلیثانیه)
|
||||||
|
CreatedAt DATETIME2 NOT NULL, -- زمان ایجاد
|
||||||
|
|
||||||
|
-- Foreign Keys
|
||||||
|
FOREIGN KEY (DeviceId) REFERENCES Devices(Id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (UserId) REFERENCES Users(Id) ON DELETE SET NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Indexes برای کوئری سریع
|
||||||
|
CREATE INDEX IX_AIQueries_DeviceId ON AIQueries(DeviceId);
|
||||||
|
CREATE INDEX IX_AIQueries_UserId ON AIQueries(UserId);
|
||||||
|
CREATE INDEX IX_AIQueries_CreatedAt ON AIQueries(CreatedAt);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 نحوه استفاده
|
||||||
|
|
||||||
|
### 1. پرسیدن سوال با ذخیره خودکار
|
||||||
|
|
||||||
|
**درخواست:**
|
||||||
|
```http
|
||||||
|
POST /api/ai/ask
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"question": "دمای مناسب اتاق چقدر است؟",
|
||||||
|
"systemPrompt": "شما یک مشاور خانه هوشمند هستید",
|
||||||
|
"deviceId": 123,
|
||||||
|
"userId": 456
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**پاسخ:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "دمای مناسب اتاق چقدر است؟",
|
||||||
|
"answer": "دمای مناسب اتاق برای راحتی معمولاً بین 20 تا 24 درجه سانتیگراد است...",
|
||||||
|
"deviceId": 123,
|
||||||
|
"tokens": {
|
||||||
|
"prompt": 25,
|
||||||
|
"completion": 150,
|
||||||
|
"total": 175
|
||||||
|
},
|
||||||
|
"responseTimeMs": 1234,
|
||||||
|
"timestamp": "2025-12-16T12:00:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. دریافت تاریخچه سوالات یک دستگاه
|
||||||
|
|
||||||
|
**درخواست:**
|
||||||
|
```http
|
||||||
|
GET /api/ai/history/device/123?take=50
|
||||||
|
```
|
||||||
|
|
||||||
|
**پاسخ:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"question": "دمای مناسب اتاق چقدر است؟",
|
||||||
|
"answer": "دمای مناسب اتاق...",
|
||||||
|
"totalTokens": 175,
|
||||||
|
"promptTokens": 25,
|
||||||
|
"completionTokens": 150,
|
||||||
|
"model": "deepseek-chat",
|
||||||
|
"responseTimeMs": 1234,
|
||||||
|
"createdAt": "2025-12-16T12:00:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"totalTokens": 5432
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. دریافت آمار کلی
|
||||||
|
|
||||||
|
**درخواست:**
|
||||||
|
```http
|
||||||
|
GET /api/ai/stats
|
||||||
|
```
|
||||||
|
|
||||||
|
**پاسخ:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"totalQueries": 1523,
|
||||||
|
"totalTokensUsed": 254789,
|
||||||
|
"totalPromptTokens": 89234,
|
||||||
|
"totalCompletionTokens": 165555,
|
||||||
|
"averageResponseTimeMs": 1456.78,
|
||||||
|
"todayQueries": 45,
|
||||||
|
"todayTokens": 7890
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 API Endpoints جدید
|
||||||
|
|
||||||
|
### 1. POST /api/ai/ask
|
||||||
|
پرسیدن سوال ساده با ذخیره خودکار
|
||||||
|
|
||||||
|
**پارامترها:**
|
||||||
|
- `question` (required): سوال
|
||||||
|
- `systemPrompt` (optional): زمینه برای AI
|
||||||
|
- `deviceId` (optional): شماره دستگاه
|
||||||
|
- `userId` (optional): شماره کاربر
|
||||||
|
|
||||||
|
### 2. POST /api/ai/chat
|
||||||
|
چت پیشرفته با ذخیره خودکار
|
||||||
|
|
||||||
|
**پارامترها:**
|
||||||
|
- `messages` (required): لیست پیامها
|
||||||
|
- `model` (optional): مدل AI
|
||||||
|
- `temperature` (optional): پارامتر خلاقیت
|
||||||
|
- `maxTokens` (optional): حداکثر توکن پاسخ
|
||||||
|
- `deviceId` (optional): شماره دستگاه
|
||||||
|
- `userId` (optional): شماره کاربر
|
||||||
|
|
||||||
|
### 3. POST /api/ai/suggest
|
||||||
|
دریافت پیشنهاد برای خانه هوشمند
|
||||||
|
|
||||||
|
**پارامترها:**
|
||||||
|
- `deviceContext` (required): اطلاعات دستگاه
|
||||||
|
- `deviceId` (optional): شماره دستگاه
|
||||||
|
- `userId` (optional): شماره کاربر
|
||||||
|
|
||||||
|
### 4. GET /api/ai/history/device/{deviceId}
|
||||||
|
دریافت تاریخچه سوالات یک دستگاه
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `take` (optional, default: 50): تعداد رکورد
|
||||||
|
|
||||||
|
### 5. GET /api/ai/stats
|
||||||
|
دریافت آمار کلی استفاده از AI
|
||||||
|
|
||||||
|
## 💡 مثالهای عملی
|
||||||
|
|
||||||
|
### مثال 1: سوال درباره دستگاه خاص
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5000/api/ai/ask \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"question": "دمای فعلی بالاست، چه کنم؟",
|
||||||
|
"deviceId": 123,
|
||||||
|
"userId": 456
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### مثال 2: دریافت تاریخچه
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5000/api/ai/history/device/123
|
||||||
|
```
|
||||||
|
|
||||||
|
### مثال 3: دریافت آمار
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5000/api/ai/stats
|
||||||
|
```
|
||||||
|
|
||||||
|
### مثال 4: پیشنهاد برای دستگاه
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5000/api/ai/suggest \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"deviceContext": "دمای اتاق: 28 درجه، رطوبت: 65%, ساعت: 14:00",
|
||||||
|
"deviceId": 123
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 کوئریهای مفید SQL
|
||||||
|
|
||||||
|
### 1. پرتکرارترین سوالات
|
||||||
|
```sql
|
||||||
|
SELECT Question, COUNT(*) as Count
|
||||||
|
FROM AIQueries
|
||||||
|
GROUP BY Question
|
||||||
|
ORDER BY Count DESC
|
||||||
|
LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. مصرف توکن به تفکیک دستگاه
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
d.DeviceName,
|
||||||
|
COUNT(aq.Id) as QueryCount,
|
||||||
|
SUM(aq.TotalTokens) as TotalTokens,
|
||||||
|
AVG(aq.TotalTokens) as AvgTokens
|
||||||
|
FROM AIQueries aq
|
||||||
|
JOIN Devices d ON aq.DeviceId = d.Id
|
||||||
|
GROUP BY d.DeviceName
|
||||||
|
ORDER BY TotalTokens DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. سوالات امروز
|
||||||
|
```sql
|
||||||
|
SELECT *
|
||||||
|
FROM AIQueries
|
||||||
|
WHERE CAST(CreatedAt AS DATE) = CAST(GETDATE() AS DATE)
|
||||||
|
ORDER BY CreatedAt DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. میانگین زمان پاسخ
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
Model,
|
||||||
|
COUNT(*) as QueryCount,
|
||||||
|
AVG(ResponseTimeMs) as AvgResponseTime,
|
||||||
|
MIN(ResponseTimeMs) as MinResponseTime,
|
||||||
|
MAX(ResponseTimeMs) as MaxResponseTime
|
||||||
|
FROM AIQueries
|
||||||
|
WHERE ResponseTimeMs IS NOT NULL
|
||||||
|
GROUP BY Model;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 گزارشهای آماری
|
||||||
|
|
||||||
|
### مصرف روزانه
|
||||||
|
```csharp
|
||||||
|
public async Task<DailyUsageReport> GetDailyUsage(DateTime date)
|
||||||
|
{
|
||||||
|
var queries = await dbContext.AIQueries
|
||||||
|
.Where(q => q.CreatedAt.Date == date.Date)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return new DailyUsageReport
|
||||||
|
{
|
||||||
|
Date = date,
|
||||||
|
TotalQueries = queries.Count,
|
||||||
|
TotalTokens = queries.Sum(q => q.TotalTokens),
|
||||||
|
UniqueDevices = queries.Select(q => q.DeviceId).Distinct().Count()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### مصرف هر دستگاه
|
||||||
|
```csharp
|
||||||
|
public async Task<DeviceUsageReport> GetDeviceUsage(int deviceId)
|
||||||
|
{
|
||||||
|
var queries = await dbContext.AIQueries
|
||||||
|
.Where(q => q.DeviceId == deviceId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return new DeviceUsageReport
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
TotalQueries = queries.Count,
|
||||||
|
TotalTokens = queries.Sum(q => q.TotalTokens),
|
||||||
|
AverageResponseTime = queries.Average(q => q.ResponseTimeMs ?? 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚠️ نکات مهم
|
||||||
|
|
||||||
|
### 1. هزینه
|
||||||
|
- هر توکن هزینه دارد
|
||||||
|
- با استفاده از آمار، مصرف را کنترل کنید
|
||||||
|
- برای کاهش هزینه، سوالات مشابه را cache کنید
|
||||||
|
|
||||||
|
### 2. عملکرد
|
||||||
|
- Index ها برای کوئری سریع اضافه شدهاند
|
||||||
|
- برای حجم بالا، از pagination استفاده کنید
|
||||||
|
- رکوردهای قدیمی را Archive کنید
|
||||||
|
|
||||||
|
### 3. حریم خصوصی
|
||||||
|
- سوالات کاربران ذخیره میشوند
|
||||||
|
- از این دادهها با احتیاط استفاده کنید
|
||||||
|
- در صورت نیاز، امکان حذف تاریخچه اضافه کنید
|
||||||
|
|
||||||
|
## 🔧 اعمال تغییرات در دیتابیس
|
||||||
|
|
||||||
|
Migration ایجاد شده و آماده اجرا است:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd GreenHome.Infrastructure
|
||||||
|
dotnet ef database update --startup-project ../GreenHome.Api
|
||||||
|
```
|
||||||
|
|
||||||
|
یا اگر برنامه را اجرا کنید، Migration به صورت خودکار اعمال میشود (در `Program.cs` تنظیم شده).
|
||||||
|
|
||||||
|
## 📚 مستندات مرتبط
|
||||||
|
|
||||||
|
- **Entity**: `GreenHome.Domain/AIQuery.cs`
|
||||||
|
- **Service**: `GreenHome.Infrastructure/AIQueryService.cs`
|
||||||
|
- **Interface**: `GreenHome.Application/IAIQueryService.cs`
|
||||||
|
- **Controller**: `GreenHome.Api/Controllers/AIController.cs`
|
||||||
|
- **Migration**: `GreenHome.Infrastructure/Migrations/20251216113127_AddAIQueryTable.cs`
|
||||||
|
|
||||||
|
## 🎯 استفادههای پیشرفته
|
||||||
|
|
||||||
|
### 1. تحلیل رفتار کاربر
|
||||||
|
```csharp
|
||||||
|
var userQueries = await aiQueryService.GetUserQueriesAsync(userId, 100);
|
||||||
|
var topics = ExtractTopics(userQueries);
|
||||||
|
// تحلیل علایق کاربر
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. بهینهسازی پاسخها
|
||||||
|
```csharp
|
||||||
|
// پیدا کردن سوالات با زمان پاسخ بالا
|
||||||
|
var slowQueries = await dbContext.AIQueries
|
||||||
|
.Where(q => q.ResponseTimeMs > 3000)
|
||||||
|
.ToListAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. گزارش هزینه
|
||||||
|
```csharp
|
||||||
|
// محاسبه هزینه بر اساس توکن
|
||||||
|
var totalTokens = await aiQueryService.GetDeviceTotalTokensAsync(deviceId);
|
||||||
|
var estimatedCost = CalculateCost(totalTokens);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**نکته:** تمام سوالات و پاسخها اکنون به صورت خودکار ذخیره میشوند و نیازی به کار اضافی نیست! ✨
|
||||||
|
|
||||||
230
src/ALERT_SYSTEM_UPDATE.md
Normal file
230
src/ALERT_SYSTEM_UPDATE.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# سیستم جدید هشدارهای شرطی
|
||||||
|
|
||||||
|
## تغییرات اعمال شده
|
||||||
|
|
||||||
|
### 1. تغییرات در تنظیمات دستگاه (`DeviceSettings`)
|
||||||
|
|
||||||
|
#### فیلدهای حذف شده:
|
||||||
|
- تمام فیلدهای `Min` و `Max` برای سنسورها حذف شدند:
|
||||||
|
- `DangerMaxTemperature`, `DangerMinTemperature`
|
||||||
|
- `MaxTemperature`, `MinTemperature`
|
||||||
|
- `MaxGasPPM`, `MinGasPPM`
|
||||||
|
- `MaxLux`, `MinLux`
|
||||||
|
- `MaxHumidityPercent`, `MinHumidityPercent`
|
||||||
|
|
||||||
|
#### فیلدهای جدید:
|
||||||
|
- `Province` (استان) - نوع: string
|
||||||
|
- `City` (شهر) - نوع: string
|
||||||
|
- `Latitude` (عرض جغرافیایی) - نوع: decimal? (اختیاری)
|
||||||
|
- `Longitude` (طول جغرافیایی) - نوع: decimal? (اختیاری)
|
||||||
|
|
||||||
|
### 2. مدلهای جدید برای شرایط هشدار
|
||||||
|
|
||||||
|
#### `AlertCondition` - شرط هشدار
|
||||||
|
هر شرط هشدار شامل موارد زیر است:
|
||||||
|
- `DeviceId`: شناسه دستگاه
|
||||||
|
- `NotificationType`: نوع اعلان (تماس یا پیامک)
|
||||||
|
- `Call = 0`: تماس صوتی
|
||||||
|
- `SMS = 1`: پیامک
|
||||||
|
- `TimeType`: زمان اعمال شرط
|
||||||
|
- `Day = 0`: فقط روز
|
||||||
|
- `Night = 1`: فقط شب
|
||||||
|
- `Always = 2`: همیشه
|
||||||
|
- `CallCooldownMinutes`: فاصله زمانی بین تماسهای هشدار (پیشفرض: 60 دقیقه)
|
||||||
|
- `SmsCooldownMinutes`: فاصله زمانی بین پیامکهای هشدار (پیشفرض: 15 دقیقه)
|
||||||
|
- `IsEnabled`: وضعیت فعال/غیرفعال بودن شرط
|
||||||
|
- `Rules`: لیست قوانین (با AND به هم متصل میشوند)
|
||||||
|
|
||||||
|
#### `AlertRule` - قانون شرط
|
||||||
|
هر قانون شامل:
|
||||||
|
- `SensorType`: نوع سنسور
|
||||||
|
- `Temperature = 0`: دما
|
||||||
|
- `Humidity = 1`: رطوبت
|
||||||
|
- `Soil = 2`: رطوبت خاک
|
||||||
|
- `Gas = 3`: گاز
|
||||||
|
- `Lux = 4`: نور
|
||||||
|
- `ComparisonType`: نوع مقایسه
|
||||||
|
- `GreaterThan = 0`: بیشتر از
|
||||||
|
- `LessThan = 1`: کمتر از
|
||||||
|
- `Between = 2`: بین دو عدد
|
||||||
|
- `OutOfRange = 3`: خارج از محدوده
|
||||||
|
- `Value1`: مقدار عددی اول
|
||||||
|
- `Value2`: مقدار عددی دوم (برای Between و OutOfRange)
|
||||||
|
- `Order`: ترتیب نمایش
|
||||||
|
|
||||||
|
### 3. API های جدید
|
||||||
|
|
||||||
|
#### مدیریت شرایط هشدار (`/api/AlertConditions`)
|
||||||
|
|
||||||
|
**دریافت شرایط یک دستگاه:**
|
||||||
|
```http
|
||||||
|
GET /api/AlertConditions/device/{deviceId}
|
||||||
|
```
|
||||||
|
|
||||||
|
**دریافت یک شرط با ID:**
|
||||||
|
```http
|
||||||
|
GET /api/AlertConditions/{id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**ایجاد شرط جدید:**
|
||||||
|
```http
|
||||||
|
POST /api/AlertConditions
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"deviceId": 1,
|
||||||
|
"notificationType": 1, // 0=Call, 1=SMS
|
||||||
|
"timeType": 0, // 0=Day, 1=Night, 2=Always
|
||||||
|
"callCooldownMinutes": 60,
|
||||||
|
"smsCooldownMinutes": 15,
|
||||||
|
"isEnabled": true,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"sensorType": 0, // 0=Temperature, 1=Humidity, 2=Soil, 3=Gas, 4=Lux
|
||||||
|
"comparisonType": 0, // 0=GreaterThan, 1=LessThan, 2=Between, 3=OutOfRange
|
||||||
|
"value1": 30.0,
|
||||||
|
"value2": null, // فقط برای Between و OutOfRange
|
||||||
|
"order": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sensorType": 1, // Humidity
|
||||||
|
"comparisonType": 2, // Between
|
||||||
|
"value1": 40.0,
|
||||||
|
"value2": 60.0,
|
||||||
|
"order": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**بهروزرسانی شرط:**
|
||||||
|
```http
|
||||||
|
PUT /api/AlertConditions
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"notificationType": 1,
|
||||||
|
"timeType": 0,
|
||||||
|
"callCooldownMinutes": 60,
|
||||||
|
"smsCooldownMinutes": 15,
|
||||||
|
"isEnabled": true,
|
||||||
|
"rules": [...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**حذف شرط:**
|
||||||
|
```http
|
||||||
|
DELETE /api/AlertConditions/{id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**فعال/غیرفعال کردن شرط:**
|
||||||
|
```http
|
||||||
|
PATCH /api/AlertConditions/{id}/toggle
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
true // یا false
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. محاسبه روز/شب
|
||||||
|
|
||||||
|
سرویس `SunCalculatorService` بر اساس موقعیت جغرافیایی (Latitude/Longitude) و زمان جاری، طلوع و غروب خورشید را محاسبه کرده و مشخص میکند که آیا زمان فعلی روز است یا شب.
|
||||||
|
|
||||||
|
### 5. نحوه عملکرد سیستم هشدار جدید
|
||||||
|
|
||||||
|
1. هنگام دریافت داده از دستگاه (`/api/Telemetry/AddData`)
|
||||||
|
2. تمام شرایط فعال (`IsEnabled=true`) دستگاه بررسی میشوند
|
||||||
|
3. برای هر شرط:
|
||||||
|
- اگر `TimeType` تنظیم شده باشد، زمان روز/شب چک میشود
|
||||||
|
- تمام قوانین (`Rules`) با منطق AND چک میشوند
|
||||||
|
- اگر همه قوانین برقرار باشند، هشدار ارسال میشود
|
||||||
|
4. هشدار فقط در صورتی ارسال میشود که:
|
||||||
|
- از آخرین هشدار همان شرط، زمان کافی گذشته باشد (بر اساس `CallCooldownMinutes` یا `SmsCooldownMinutes`)
|
||||||
|
5. هشدار به صورت پیامک یا تماس صوتی ارسال میشود
|
||||||
|
|
||||||
|
### 6. مثالهای کاربردی
|
||||||
|
|
||||||
|
#### مثال 1: هشدار دمای بالا در روز
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceId": 1,
|
||||||
|
"notificationType": 1, // SMS
|
||||||
|
"timeType": 0, // Day only
|
||||||
|
"smsCooldownMinutes": 15,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"sensorType": 0, // Temperature
|
||||||
|
"comparisonType": 0, // GreaterThan
|
||||||
|
"value1": 35.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مثال 2: هشدار دما و رطوبت در شب
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceId": 1,
|
||||||
|
"notificationType": 0, // Call
|
||||||
|
"timeType": 1, // Night only
|
||||||
|
"callCooldownMinutes": 60,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"sensorType": 0, // Temperature
|
||||||
|
"comparisonType": 1, // LessThan
|
||||||
|
"value1": 10.0,
|
||||||
|
"order": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sensorType": 1, // Humidity
|
||||||
|
"comparisonType": 0, // GreaterThan
|
||||||
|
"value1": 80.0,
|
||||||
|
"order": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**توضیح**: اگر دما کمتر از 10 درجه AND رطوبت بیشتر از 80 درصد باشد، در شب تماس بگیر.
|
||||||
|
|
||||||
|
#### مثال 3: رطوبت خارج از محدوده
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceId": 1,
|
||||||
|
"notificationType": 1, // SMS
|
||||||
|
"timeType": 2, // Always
|
||||||
|
"smsCooldownMinutes": 15,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"sensorType": 1, // Humidity
|
||||||
|
"comparisonType": 3, // OutOfRange
|
||||||
|
"value1": 30.0,
|
||||||
|
"value2": 70.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**توضیح**: اگر رطوبت کمتر از 30 یا بیشتر از 70 باشد، همیشه پیامک بفرست.
|
||||||
|
|
||||||
|
### 7. تغییرات در Database
|
||||||
|
|
||||||
|
Migration جدید (`UpdateAlertSystemWithConditions`) شامل:
|
||||||
|
- حذف ستونهای min/max از `DeviceSettings`
|
||||||
|
- اضافه کردن ستونهای `Province`, `City`, `Latitude`, `Longitude` به `DeviceSettings`
|
||||||
|
- ایجاد جدول `AlertConditions`
|
||||||
|
- ایجاد جدول `AlertRules`
|
||||||
|
- بهروزرسانی جدول `AlertNotifications` برای ارتباط با `AlertCondition`
|
||||||
|
|
||||||
|
### 8. سرویسهای جدید
|
||||||
|
|
||||||
|
- `IAlertConditionService` / `AlertConditionService`: مدیریت شرایط هشدار
|
||||||
|
- `ISunCalculatorService` / `SunCalculatorService`: محاسبه طلوع/غروب و تشخیص روز/شب
|
||||||
|
- `AlertService`: بازنویسی کامل برای پشتیبانی از سیستم شرطی جدید
|
||||||
|
|
||||||
|
### 9. نکات مهم
|
||||||
|
|
||||||
|
1. **Migration**: قبل از اجرا، حتماً backup از database بگیرید چون فیلدهای قدیمی حذف میشوند
|
||||||
|
2. **Latitude/Longitude**: برای استفاده از قابلیت روز/شب، حتماً مختصات جغرافیایی را در تنظیمات دستگاه وارد کنید
|
||||||
|
3. **Cooldown**: فاصله زمانی بین هشدارها قابل تنظیم برای هر شرط است
|
||||||
|
4. **AND Logic**: تمام قوانین یک شرط با منطق AND به هم متصل میشوند
|
||||||
|
5. **Multiple Conditions**: میتوانید چندین شرط مجزا برای یک دستگاه تعریف کنید
|
||||||
|
|
||||||
119
src/CHANGES_DAILY_REPORT.md
Normal file
119
src/CHANGES_DAILY_REPORT.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# خلاصه تغییرات - API گزارش روزانه
|
||||||
|
|
||||||
|
## تاریخ: 1403/09/26 (2024/12/16)
|
||||||
|
|
||||||
|
### فایلهای جدید ایجاد شده:
|
||||||
|
|
||||||
|
1. **GreenHome.Domain/DailyReport.cs**
|
||||||
|
- Entity برای ذخیره گزارشهای روزانه
|
||||||
|
- شامل اطلاعات تحلیل AI، مصرف توکن، و متادیتای مرتبط
|
||||||
|
|
||||||
|
2. **GreenHome.Application/IDailyReportService.cs**
|
||||||
|
- Interface سرویس گزارش روزانه
|
||||||
|
|
||||||
|
3. **GreenHome.Infrastructure/DailyReportService.cs**
|
||||||
|
- پیادهسازی کامل سرویس گزارش روزانه
|
||||||
|
- شامل لاجیک نمونهبرداری، ارتباط با DeepSeek، و کش
|
||||||
|
|
||||||
|
4. **GreenHome.Api/Controllers/DailyReportController.cs**
|
||||||
|
- Controller جدید با endpoint برای دریافت گزارش
|
||||||
|
|
||||||
|
5. **GreenHome.Infrastructure/Migrations/20251216152746_AddDailyReportsTable.cs**
|
||||||
|
- Migration برای ایجاد جدول DailyReports
|
||||||
|
|
||||||
|
6. **DAILY_REPORT_API.md**
|
||||||
|
- مستندات کامل API
|
||||||
|
|
||||||
|
### فایلهای ویرایش شده:
|
||||||
|
|
||||||
|
1. **GreenHome.Application/Dtos.cs**
|
||||||
|
- افزودن `DailyReportRequest`
|
||||||
|
- افزودن `DailyReportResponse`
|
||||||
|
|
||||||
|
2. **GreenHome.Infrastructure/GreenHomeDbContext.cs**
|
||||||
|
- افزودن `DbSet<DailyReport>`
|
||||||
|
- پیکربندی entity در `OnModelCreating`
|
||||||
|
|
||||||
|
3. **GreenHome.Api/Program.cs**
|
||||||
|
- ثبت `IDailyReportService` در DI container
|
||||||
|
|
||||||
|
4. **GreenHome.Infrastructure/GreenHome.Infrastructure.csproj**
|
||||||
|
- افزودن reference به `GreenHome.AI.DeepSeek`
|
||||||
|
|
||||||
|
## ویژگیهای کلیدی:
|
||||||
|
|
||||||
|
### 1. کش هوشمند
|
||||||
|
- گزارشهای قبلی از دیتابیس خوانده میشوند
|
||||||
|
- صرفهجویی در مصرف توکن و هزینه
|
||||||
|
|
||||||
|
### 2. نمونهبرداری بهینه
|
||||||
|
- از هر 20 رکورد، فقط 1 رکورد انتخاب میشود
|
||||||
|
- کاهش 95% در مصرف توکن
|
||||||
|
|
||||||
|
### 3. تحلیل جامع
|
||||||
|
- دما، رطوبت، نور، و کیفیت هوا (CO)
|
||||||
|
- روندهای روزانه و پیشنهادات بهبود
|
||||||
|
|
||||||
|
### 4. مدیریت خطا
|
||||||
|
- بررسی اعتبار ورودیها
|
||||||
|
- لاگ کامل عملیات
|
||||||
|
- پیامهای خطای واضح به فارسی
|
||||||
|
|
||||||
|
### 5. بهینهسازی دیتابیس
|
||||||
|
- Unique constraint بر روی (DeviceId, PersianDate)
|
||||||
|
- Indexهای مناسب برای جستجوی سریع
|
||||||
|
- Cascade delete برای یکپارچگی داده
|
||||||
|
|
||||||
|
## نحوه استفاده:
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/DailyReport?deviceId=1&persianDate=1403/09/26
|
||||||
|
```
|
||||||
|
|
||||||
|
## پیشنیازها:
|
||||||
|
|
||||||
|
1. کانفیگ DeepSeek API در `appsettings.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DeepSeek": {
|
||||||
|
"ApiKey": "your-api-key",
|
||||||
|
"BaseUrl": "https://api.deepseek.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. اجرای migration:
|
||||||
|
```bash
|
||||||
|
dotnet ef database update
|
||||||
|
```
|
||||||
|
یا به صورت خودکار در startup برنامه اعمال میشود.
|
||||||
|
|
||||||
|
## نکات امنیتی:
|
||||||
|
|
||||||
|
- API key باید در environment variable یا Azure Key Vault نگهداری شود
|
||||||
|
- در production، rate limiting اضافه کنید
|
||||||
|
- برای دسترسی به API، authentication لازم است (در نسخه بعدی)
|
||||||
|
|
||||||
|
## تست:
|
||||||
|
|
||||||
|
1. مطمئن شوید دیتابیس شامل رکوردهای تلمتری برای تاریخ مورد نظر است
|
||||||
|
2. درخواست اول باید گزارش جدید ایجاد کند (`fromCache: false`)
|
||||||
|
3. درخواست دوم با همان تاریخ باید از کش برگردد (`fromCache: true`)
|
||||||
|
|
||||||
|
## آمار عملکرد:
|
||||||
|
|
||||||
|
- زمان پاسخ اولین درخواست: ~3-5 ثانیه (شامل فراخوانی AI)
|
||||||
|
- زمان پاسخ درخواستهای بعدی: <100ms (از کش)
|
||||||
|
- مصرف توکن برای یک روز با 288 رکورد: ~800-1500 توکن
|
||||||
|
- بدون نمونهبرداری: ~15000-20000 توکن (95% کاهش!)
|
||||||
|
|
||||||
|
## TODO (پیشنهادات آینده):
|
||||||
|
|
||||||
|
- [ ] اضافه کردن فیلتر تاریخ (از تا) برای دریافت چندین گزارش
|
||||||
|
- [ ] ایجاد endpoint برای لیست کردن تمام گزارشهای یک دستگاه
|
||||||
|
- [ ] امکان حذف و ایجاد مجدد گزارش (برای مدیران)
|
||||||
|
- [ ] اضافه کردن chart و نمودار به پاسخ
|
||||||
|
- [ ] ارسال گزارش به ایمیل یا SMS
|
||||||
|
- [ ] مقایسه گزارشهای چند روزه
|
||||||
|
- [ ] پیشنهادات اتوماتیک برای تنظیمات دستگاه
|
||||||
|
|
||||||
246
src/CHANGES_SUMMARY.md
Normal file
246
src/CHANGES_SUMMARY.md
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
# 📝 خلاصه تغییرات - سیستم ذخیره و ردیابی سوالات AI
|
||||||
|
|
||||||
|
## ✅ تغییرات اعمال شده
|
||||||
|
|
||||||
|
### 1. Entity جدید در Domain
|
||||||
|
**فایل:** `GreenHome.Domain/AIQuery.cs`
|
||||||
|
- ذخیره سوال و پاسخ
|
||||||
|
- ذخیره اطلاعات توکن (PromptTokens, CompletionTokens, TotalTokens)
|
||||||
|
- ارتباط با Device (DeviceId)
|
||||||
|
- ارتباط با User (UserId)
|
||||||
|
- ذخیره Model و Temperature
|
||||||
|
- ذخیره زمان پاسخ (ResponseTimeMs)
|
||||||
|
- تاریخ ایجاد (CreatedAt)
|
||||||
|
|
||||||
|
### 2. آپدیت DbContext
|
||||||
|
**فایل:** `GreenHome.Infrastructure/GreenHomeDbContext.cs`
|
||||||
|
- اضافه شدن `DbSet<AIQuery>`
|
||||||
|
- تنظیمات Entity Framework
|
||||||
|
- Foreign Keys به Device و User
|
||||||
|
- Index ها برای کوئری سریع
|
||||||
|
|
||||||
|
### 3. Interface و Service جدید
|
||||||
|
**فایلها:**
|
||||||
|
- `GreenHome.Application/IAIQueryService.cs` - Interface
|
||||||
|
- `GreenHome.Infrastructure/AIQueryService.cs` - پیادهسازی
|
||||||
|
|
||||||
|
**قابلیتها:**
|
||||||
|
- `SaveQueryAsync()` - ذخیره سوال
|
||||||
|
- `GetDeviceQueriesAsync()` - دریافت تاریخچه دستگاه
|
||||||
|
- `GetUserQueriesAsync()` - دریافت تاریخچه کاربر
|
||||||
|
- `GetDeviceTotalTokensAsync()` - مجموع توکنهای دستگاه
|
||||||
|
- `GetUserTotalTokensAsync()` - مجموع توکنهای کاربر
|
||||||
|
- `GetRecentQueriesAsync()` - آخرین سوالات
|
||||||
|
- `GetStatsAsync()` - آمار کلی
|
||||||
|
|
||||||
|
### 4. آپدیت AIController
|
||||||
|
**فایل:** `GreenHome.Api/Controllers/AIController.cs`
|
||||||
|
|
||||||
|
**تغییرات:**
|
||||||
|
- Inject کردن `IAIQueryService`
|
||||||
|
- اضافه شدن `DeviceId` و `UserId` به Request Models
|
||||||
|
- ذخیره خودکار تمام سوالات و پاسخها
|
||||||
|
- اندازهگیری زمان پاسخ
|
||||||
|
- برگرداندن اطلاعات توکن در Response
|
||||||
|
|
||||||
|
**Endpoints جدید:**
|
||||||
|
- `GET /api/ai/history/device/{deviceId}` - تاریخچه سوالات دستگاه
|
||||||
|
- `GET /api/ai/stats` - آمار کلی
|
||||||
|
|
||||||
|
**Endpoints بهروز شده:**
|
||||||
|
- `POST /api/ai/ask` - حالا DeviceId و UserId میگیرد
|
||||||
|
- `POST /api/ai/chat` - حالا DeviceId و UserId میگیرد
|
||||||
|
- `POST /api/ai/suggest` - حالا DeviceId و UserId میگیرد
|
||||||
|
|
||||||
|
### 5. ثبت Service در DI
|
||||||
|
**فایل:** `GreenHome.Api/Program.cs`
|
||||||
|
- اضافه شدن `IAIQueryService` به Dependency Injection
|
||||||
|
|
||||||
|
### 6. Migration دیتابیس
|
||||||
|
**فایل:** `GreenHome.Infrastructure/Migrations/20251216113127_AddAIQueryTable.cs`
|
||||||
|
- ایجاد جدول `AIQueries`
|
||||||
|
- Foreign Keys
|
||||||
|
- Indexes
|
||||||
|
|
||||||
|
### 7. مستندات
|
||||||
|
**فایلها:**
|
||||||
|
- `AI_QUERY_TRACKING.md` - راهنمای کامل استفاده
|
||||||
|
- `CHANGES_SUMMARY.md` - این فایل
|
||||||
|
|
||||||
|
## 📊 ساختار جدول AIQueries
|
||||||
|
|
||||||
|
```
|
||||||
|
AIQueries
|
||||||
|
├── Id (PK)
|
||||||
|
├── DeviceId (FK -> Devices) - اختیاری
|
||||||
|
├── UserId (FK -> Users) - اختیاری
|
||||||
|
├── Question (nvarchar(max))
|
||||||
|
├── Answer (nvarchar(max))
|
||||||
|
├── PromptTokens (int)
|
||||||
|
├── CompletionTokens (int)
|
||||||
|
├── TotalTokens (int)
|
||||||
|
├── Model (nvarchar(100))
|
||||||
|
├── Temperature (float) - اختیاری
|
||||||
|
├── ResponseTimeMs (bigint) - اختیاری
|
||||||
|
└── CreatedAt (datetime2)
|
||||||
|
|
||||||
|
Indexes:
|
||||||
|
- IX_AIQueries_DeviceId
|
||||||
|
- IX_AIQueries_UserId
|
||||||
|
- IX_AIQueries_CreatedAt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 نحوه اعمال تغییرات
|
||||||
|
|
||||||
|
### گزینه 1: خودکار (پیشنهادی)
|
||||||
|
فقط برنامه را اجرا کنید، Migration به صورت خودکار اعمال میشود:
|
||||||
|
```bash
|
||||||
|
cd GreenHome.Api
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
### گزینه 2: دستی
|
||||||
|
```bash
|
||||||
|
cd GreenHome.Infrastructure
|
||||||
|
dotnet ef database update --startup-project ../GreenHome.Api
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📖 مثال استفاده
|
||||||
|
|
||||||
|
### قبل از تغییرات:
|
||||||
|
```json
|
||||||
|
POST /api/ai/ask
|
||||||
|
{
|
||||||
|
"question": "دمای مناسب چند است?"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### بعد از تغییرات:
|
||||||
|
```json
|
||||||
|
POST /api/ai/ask
|
||||||
|
{
|
||||||
|
"question": "دمای مناسب چند است؟",
|
||||||
|
"deviceId": 123,
|
||||||
|
"userId": 456
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response:
|
||||||
|
{
|
||||||
|
"question": "دمای مناسب چند است؟",
|
||||||
|
"answer": "بین 20 تا 24 درجه...",
|
||||||
|
"deviceId": 123,
|
||||||
|
"tokens": {
|
||||||
|
"prompt": 15,
|
||||||
|
"completion": 85,
|
||||||
|
"total": 100
|
||||||
|
},
|
||||||
|
"responseTimeMs": 1234,
|
||||||
|
"timestamp": "2025-12-16T12:00:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 مزایای جدید
|
||||||
|
|
||||||
|
1. ✅ **ردیابی کامل** - تمام سوالات و پاسخها ذخیره میشوند
|
||||||
|
2. ✅ **مدیریت هزینه** - میزان دقیق مصرف توکن قابل محاسبه است
|
||||||
|
3. ✅ **تحلیل عملکرد** - زمان پاسخدهی اندازهگیری میشود
|
||||||
|
4. ✅ **تاریخچه** - سوالات قبلی هر دستگاه قابل مشاهده است
|
||||||
|
5. ✅ **آمار** - آمار کلی و تفصیلی در دسترس است
|
||||||
|
6. ✅ **گزارشگیری** - امکان تولید گزارشهای مختلف
|
||||||
|
|
||||||
|
## 🔍 دریافت اطلاعات
|
||||||
|
|
||||||
|
### تاریخچه یک دستگاه:
|
||||||
|
```bash
|
||||||
|
GET /api/ai/history/device/123?take=50
|
||||||
|
```
|
||||||
|
|
||||||
|
### آمار کلی:
|
||||||
|
```bash
|
||||||
|
GET /api/ai/stats
|
||||||
|
```
|
||||||
|
|
||||||
|
### در کد C#:
|
||||||
|
```csharp
|
||||||
|
// تاریخچه دستگاه
|
||||||
|
var queries = await aiQueryService.GetDeviceQueriesAsync(123);
|
||||||
|
|
||||||
|
// مجموع توکنها
|
||||||
|
var totalTokens = await aiQueryService.GetDeviceTotalTokensAsync(123);
|
||||||
|
|
||||||
|
// آمار
|
||||||
|
var stats = await aiQueryService.GetStatsAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 آمار قابل دسترسی
|
||||||
|
|
||||||
|
از endpoint `/api/ai/stats` میتوانید این اطلاعات را دریافت کنید:
|
||||||
|
- تعداد کل سوالات
|
||||||
|
- مجموع توکنهای استفاده شده
|
||||||
|
- توکنهای Prompt
|
||||||
|
- توکنهای Completion
|
||||||
|
- میانگین زمان پاسخ
|
||||||
|
- سوالات امروز
|
||||||
|
- توکنهای امروز
|
||||||
|
|
||||||
|
## ⚡ تغییرات Breaking
|
||||||
|
|
||||||
|
هیچ! تمام تغییرات backward compatible هستند:
|
||||||
|
- `deviceId` و `userId` اختیاری هستند
|
||||||
|
- API های قبلی همچنان کار میکنند
|
||||||
|
- فقط قابلیتهای جدید اضافه شدهاند
|
||||||
|
|
||||||
|
## 🧪 تست
|
||||||
|
|
||||||
|
### تست ذخیره سوال:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5000/api/ai/ask \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"question": "تست ذخیره سوال",
|
||||||
|
"deviceId": 1
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### تست دریافت تاریخچه:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5000/api/ai/history/device/1
|
||||||
|
```
|
||||||
|
|
||||||
|
### تست آمار:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5000/api/ai/stats
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 فایلهای تغییر یافته
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ Domain Layer:
|
||||||
|
- GreenHome.Domain/AIQuery.cs (جدید)
|
||||||
|
|
||||||
|
✅ Application Layer:
|
||||||
|
- GreenHome.Application/IAIQueryService.cs (جدید)
|
||||||
|
|
||||||
|
✅ Infrastructure Layer:
|
||||||
|
- GreenHome.Infrastructure/GreenHomeDbContext.cs (آپدیت)
|
||||||
|
- GreenHome.Infrastructure/AIQueryService.cs (جدید)
|
||||||
|
- GreenHome.Infrastructure/Migrations/20251216113127_AddAIQueryTable.cs (جدید)
|
||||||
|
|
||||||
|
✅ API Layer:
|
||||||
|
- GreenHome.Api/Controllers/AIController.cs (آپدیت)
|
||||||
|
- GreenHome.Api/Program.cs (آپدیت)
|
||||||
|
|
||||||
|
✅ Documentation:
|
||||||
|
- AI_QUERY_TRACKING.md (جدید)
|
||||||
|
- CHANGES_SUMMARY.md (جدید)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎉 آماده استفاده!
|
||||||
|
|
||||||
|
تمام تغییرات اعمال شده و سیستم آماده است. فقط کافی است:
|
||||||
|
1. برنامه را اجرا کنید
|
||||||
|
2. از API استفاده کنید
|
||||||
|
3. سوالات به صورت خودکار ذخیره میشوند!
|
||||||
|
|
||||||
|
برای اطلاعات بیشتر، فایل `AI_QUERY_TRACKING.md` را مطالعه کنید.
|
||||||
|
|
||||||
142
src/CHANGES_SUMMARY_ALERT_SYSTEM.md
Normal file
142
src/CHANGES_SUMMARY_ALERT_SYSTEM.md
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
# خلاصه تغییرات سیستم هشدار شرطی
|
||||||
|
|
||||||
|
## 📋 خلاصه کلی
|
||||||
|
|
||||||
|
سیستم هشدار قدیمی که بر اساس حداقل و حداکثر ثابت برای هر سنسور کار میکرد، به یک سیستم **شرطی پیشرفته** تبدیل شد که امکان تعریف شرایط پیچیده و انعطافپذیر را فراهم میکند.
|
||||||
|
|
||||||
|
## 🎯 ویژگیهای جدید
|
||||||
|
|
||||||
|
### 1. سیستم شرطگذاری پیشرفته
|
||||||
|
- تعریف نامحدود شرط برای هر دستگاه
|
||||||
|
- ترکیب چندین قانون با منطق AND
|
||||||
|
- انتخاب نوع اعلان (تماس یا پیامک) برای هر شرط
|
||||||
|
- تنظیم زمان اعمال شرط (روز، شب، همیشه)
|
||||||
|
|
||||||
|
### 2. مدیریت زمان هوشمند
|
||||||
|
- محاسبه خودکار طلوع و غروب خورشید بر اساس موقعیت جغرافیایی
|
||||||
|
- فیلتر کردن هشدارها بر اساس روز/شب بودن
|
||||||
|
- اضافه شدن فیلدهای استان، شهر، Latitude، Longitude به تنظیمات دستگاه
|
||||||
|
|
||||||
|
### 3. کنترل Cooldown جداگانه
|
||||||
|
- تنظیم فاصله زمانی مجزا برای تماس (پیشفرض 60 دقیقه)
|
||||||
|
- تنظیم فاصله زمانی مجزا برای پیامک (پیشفرض 15 دقیقه)
|
||||||
|
- قابل تنظیم برای هر شرط به صورت جداگانه
|
||||||
|
|
||||||
|
### 4. انواع مقایسه
|
||||||
|
- بیشتر از (GreaterThan)
|
||||||
|
- کمتر از (LessThan)
|
||||||
|
- بین دو عدد (Between)
|
||||||
|
- خارج از محدوده (OutOfRange)
|
||||||
|
|
||||||
|
## 🗂️ فایلهای ایجاد شده
|
||||||
|
|
||||||
|
### Domain Layer
|
||||||
|
- `GreenHome.Domain/AlertCondition.cs` - مدل شرط هشدار
|
||||||
|
- `GreenHome.Domain/AlertCondition.cs` (enums) - SensorType, ComparisonType, AlertNotificationType, AlertTimeType
|
||||||
|
|
||||||
|
### Application Layer
|
||||||
|
- `GreenHome.Application/IAlertConditionService.cs` - Interface سرویس مدیریت شرایط
|
||||||
|
- `GreenHome.Application/ISunCalculatorService.cs` - Interface محاسبه طلوع/غروب
|
||||||
|
- تغییرات در `GreenHome.Application/Dtos.cs` - DTOs جدید
|
||||||
|
|
||||||
|
### Infrastructure Layer
|
||||||
|
- `GreenHome.Infrastructure/AlertConditionService.cs` - سرویس مدیریت شرایط
|
||||||
|
- `GreenHome.Infrastructure/SunCalculatorService.cs` - سرویس محاسبه خورشید
|
||||||
|
- تغییرات در `GreenHome.Infrastructure/AlertService.cs` - بازنویسی کامل
|
||||||
|
- Migration جدید: `UpdateAlertSystemWithConditions`
|
||||||
|
|
||||||
|
### API Layer
|
||||||
|
- `GreenHome.Api/Controllers/AlertConditionsController.cs` - Controller جدید
|
||||||
|
|
||||||
|
## 🔄 فایلهای تغییر یافته
|
||||||
|
|
||||||
|
1. **GreenHome.Domain/DeviceSettings.cs**
|
||||||
|
- حذف فیلدهای Min/Max سنسورها
|
||||||
|
- اضافه فیلدهای Province, City, Latitude, Longitude
|
||||||
|
|
||||||
|
2. **GreenHome.Domain/AlertNotification.cs**
|
||||||
|
- تغییر از AlertType به AlertConditionId
|
||||||
|
- اضافه NotificationType
|
||||||
|
|
||||||
|
3. **GreenHome.Infrastructure/GreenHomeDbContext.cs**
|
||||||
|
- پیکربندی جداول جدید
|
||||||
|
- تغییر پیکربندی DeviceSettings و AlertNotifications
|
||||||
|
|
||||||
|
4. **GreenHome.Application/MappingProfile.cs**
|
||||||
|
- اضافه Mapping های جدید برای AlertCondition و AlertRule
|
||||||
|
|
||||||
|
5. **GreenHome.Api/Program.cs**
|
||||||
|
- ثبت IAlertConditionService
|
||||||
|
- ثبت ISunCalculatorService
|
||||||
|
|
||||||
|
6. **GreenHome.Infrastructure/GreenHome.Infrastructure.csproj**
|
||||||
|
- اضافه reference به GreenHome.VoiceCall.Avanak
|
||||||
|
|
||||||
|
## 📊 تغییرات Database
|
||||||
|
|
||||||
|
### جداول جدید:
|
||||||
|
- **AlertConditions**: شرایط هشدار
|
||||||
|
- **AlertRules**: قوانین مربوط به هر شرط
|
||||||
|
|
||||||
|
### جداول تغییر یافته:
|
||||||
|
- **DeviceSettings**:
|
||||||
|
- حذف: DangerMaxTemperature, DangerMinTemperature, MaxTemperature, MinTemperature, MaxGasPPM, MinGasPPM, MaxLux, MinLux, MaxHumidityPercent, MinHumidityPercent
|
||||||
|
- اضافه: Province, City, Latitude, Longitude
|
||||||
|
|
||||||
|
- **AlertNotifications**:
|
||||||
|
- حذف: AlertType
|
||||||
|
- اضافه: AlertConditionId, NotificationType
|
||||||
|
|
||||||
|
## 🔌 API Endpoints جدید
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/AlertConditions/device/{deviceId} - لیست شرایط یک دستگاه
|
||||||
|
GET /api/AlertConditions/{id} - دریافت یک شرط
|
||||||
|
POST /api/AlertConditions - ایجاد شرط جدید
|
||||||
|
PUT /api/AlertConditions - بهروزرسانی شرط
|
||||||
|
DELETE /api/AlertConditions/{id} - حذف شرط
|
||||||
|
PATCH /api/AlertConditions/{id}/toggle - فعال/غیرفعال کردن شرط
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ نحوه استفاده
|
||||||
|
|
||||||
|
### مثال ایجاد شرط:
|
||||||
|
```json
|
||||||
|
POST /api/AlertConditions
|
||||||
|
{
|
||||||
|
"deviceId": 1,
|
||||||
|
"notificationType": 1, // SMS
|
||||||
|
"timeType": 0, // Day only
|
||||||
|
"smsCooldownMinutes": 15,
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"sensorType": 0, // Temperature
|
||||||
|
"comparisonType": 0, // GreaterThan
|
||||||
|
"value1": 35.0,
|
||||||
|
"order": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
این شرط میگوید: **اگر در روز، دما بیشتر از 35 درجه شد، هر 15 دقیقه یکبار پیامک بفرست.**
|
||||||
|
|
||||||
|
## ⚠️ نکات مهم
|
||||||
|
|
||||||
|
1. **Migration**: حتماً قبل از اجرای migration از database بکآپ بگیرید
|
||||||
|
2. **Data Loss**: فیلدهای قدیمی Min/Max حذف میشوند و قابل بازگشت نیستند
|
||||||
|
3. **Location**: برای استفاده از قابلیت Day/Night، باید Latitude و Longitude را در تنظیمات دستگاه وارد کنید
|
||||||
|
4. **Backward Compatibility**: سیستم قدیمی دیگر کار نمیکند و باید شرایط جدید تعریف شوند
|
||||||
|
|
||||||
|
## 📝 TODO برای آینده
|
||||||
|
|
||||||
|
- [ ] پیادهسازی کامل تماس صوتی (در حال حاضر placeholder است)
|
||||||
|
- [ ] اضافه کردن تستهای واحد
|
||||||
|
- [ ] اضافه کردن Validation برای DTOs
|
||||||
|
- [ ] پیادهسازی Logging بهتر برای Debug
|
||||||
|
- [ ] اضافه کردن Dashboard برای مشاهده تاریخچه هشدارها
|
||||||
|
|
||||||
|
## 📚 مستندات
|
||||||
|
|
||||||
|
برای اطلاعات بیشتر، فایل `ALERT_SYSTEM_UPDATE.md` را مطالعه کنید.
|
||||||
|
|
||||||
145
src/DAILY_REPORT_API.md
Normal file
145
src/DAILY_REPORT_API.md
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# API گزارش تحلیل روزانه گلخانه
|
||||||
|
|
||||||
|
این API برای دریافت تحلیل هوشمصنوعی روزانه از دادههای تلمتری گلخانه طراحی شده است.
|
||||||
|
|
||||||
|
## اندپوینت
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/DailyReport
|
||||||
|
```
|
||||||
|
|
||||||
|
## پارامترها
|
||||||
|
|
||||||
|
| پارامتر | نوع | الزامی | توضیحات |
|
||||||
|
|---------|-----|--------|----------|
|
||||||
|
| `deviceId` | int | بله | شناسه دستگاه |
|
||||||
|
| `persianDate` | string | بله | تاریخ شمسی به فرمت `yyyy/MM/dd` (مثال: `1403/09/26`) |
|
||||||
|
|
||||||
|
## مثال درخواست
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/DailyReport?deviceId=1&persianDate=1403/09/26
|
||||||
|
```
|
||||||
|
|
||||||
|
## پاسخ موفق (200 OK)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"deviceId": 1,
|
||||||
|
"deviceName": "گلخانه اول",
|
||||||
|
"persianDate": "1403/09/26",
|
||||||
|
"analysis": "**وضعیت کلی:**\n\nدر طول روز 1403/09/26، شرایط گلخانه به طور کلی مطلوب بوده است. دمای متوسط حدود 25 درجه سانتیگراد، رطوبت 65 درصد و نور کافی (حدود 5000 لوکس) ثبت شده است. کیفیت هوا نیز با مقادیر CO در محدوده ایمن (کمتر از 100 PPM) مناسب بوده است.\n\n**روندهای مشاهده شده:**\n\n- دما در طول روز از 18 درجه صبح به 32 درجه ظهر رسیده و سپس کاهش یافته است.\n- رطوبت هوا در ساعات ظهر کاهش یافته ولی شب مجدداً افزایش یافته.\n- نور در ساعات صبح تا عصر در حد مطلوب و شب صفر بوده است.\n- مقادیر CO در کل روز در سطح ایمن باقی مانده.\n\n**نکات و هشدارها:**\n\n- دمای ظهر (32 درجه) کمی بالاست. توصیه میشود سیستم تهویه را بهبود دهید.\n- رطوبت شب بیش از حد است (85 درصد) که ممکن است منجر به رشد قارچ شود.\n\n**پیشنهادات:**\n\n1. نصب سیستم سایهبان خودکار برای کنترل دمای ظهر\n2. استفاده از هواکش در شب برای کاهش رطوبت\n3. بررسی سیستم آبیاری برای جلوگیری از رطوبت اضافی",
|
||||||
|
"recordCount": 288,
|
||||||
|
"sampledRecordCount": 15,
|
||||||
|
"totalTokens": 1250,
|
||||||
|
"createdAt": "2024-12-16T14:30:00Z",
|
||||||
|
"fromCache": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## پاسخهای خطا
|
||||||
|
|
||||||
|
### 400 Bad Request
|
||||||
|
درخواست نامعتبر (شناسه دستگاه یا فرمت تاریخ اشتباه)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "تاریخ شمسی باید به فرمت yyyy/MM/dd باشد"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 404 Not Found
|
||||||
|
دستگاه یا دادهای برای تاریخ مورد نظر یافت نشد
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "هیچ رکوردی برای دستگاه 1 در تاریخ 1403/09/26 یافت نشد"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 500 Internal Server Error
|
||||||
|
خطای سرور (مثلاً خطا در ارتباط با DeepSeek API)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "خطای سرور در پردازش درخواست"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## نحوه عملکرد
|
||||||
|
|
||||||
|
1. **بررسی کش:** ابتدا سیستم چک میکند آیا برای این دستگاه و تاریخ، گزارشی قبلاً ایجاد شده یا نه. اگر وجود داشته باشد، همان گزارش برگردانده میشود (`fromCache: true`) و توکن جدیدی مصرف نمیشود.
|
||||||
|
|
||||||
|
2. **استخراج دادهها:** اگر گزارش موجود نباشد، تمام رکوردهای تلمتری آن روز از دیتابیس استخراج میشوند.
|
||||||
|
|
||||||
|
3. **نمونهبرداری:** دادهها بر اساس زمان سورت میشوند و سپس از هر 20 رکورد، فقط رکورد اول انتخاب میشود. این کار برای کاهش مصرف توکن و بهینهسازی هزینه انجام میشود.
|
||||||
|
|
||||||
|
4. **ارسال به AI:** دادههای نمونهبرداری شده در قالب یک جدول ساختاریافته به DeepSeek API ارسال میشوند با درخواست تحلیل خلاصه.
|
||||||
|
|
||||||
|
5. **ذخیرهسازی:** پاسخ دریافتی به همراه اطلاعات مصرف توکن در دیتابیس ذخیره میشود.
|
||||||
|
|
||||||
|
6. **بازگشت نتیجه:** گزارش تحلیل به کاربر برگردانده میشود.
|
||||||
|
|
||||||
|
## فیلدهای تحلیل شده
|
||||||
|
|
||||||
|
API دادههای زیر را برای تحلیل در نظر میگیرد:
|
||||||
|
|
||||||
|
- **زمان** (TimestampUtc) - زمان ثبت داده
|
||||||
|
- **دما** (TemperatureC) - دمای محیط به درجه سانتیگراد
|
||||||
|
- **رطوبت** (HumidityPercent) - درصد رطوبت هوا
|
||||||
|
- **نور** (Lux) - شدت نور به لوکس
|
||||||
|
- **CO** (GasPPM) - مقدار گاز CO به PPM
|
||||||
|
|
||||||
|
## مدیریت توکن
|
||||||
|
|
||||||
|
- هر درخواست جدید توکن مصرف میکند (معمولاً 800-1500 توکن)
|
||||||
|
- گزارشهای cache شده هیچ توکن اضافی مصرف نمیکنند
|
||||||
|
- نمونهبرداری 1 از 20 رکورد، مصرف توکن را تا 95% کاهش میدهد
|
||||||
|
- اطلاعات دقیق مصرف توکن در فیلد `totalTokens` برگردانده میشود
|
||||||
|
|
||||||
|
## جدول دیتابیس
|
||||||
|
|
||||||
|
گزارشها در جدول `DailyReports` ذخیره میشوند:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE DailyReports (
|
||||||
|
Id INT PRIMARY KEY IDENTITY(1,1),
|
||||||
|
DeviceId INT NOT NULL,
|
||||||
|
PersianDate NVARCHAR(10) NOT NULL,
|
||||||
|
PersianYear INT NOT NULL,
|
||||||
|
PersianMonth INT NOT NULL,
|
||||||
|
PersianDay INT NOT NULL,
|
||||||
|
Analysis NVARCHAR(MAX) NOT NULL,
|
||||||
|
RecordCount INT NOT NULL,
|
||||||
|
SampledRecordCount INT NOT NULL,
|
||||||
|
PromptTokens INT NOT NULL,
|
||||||
|
CompletionTokens INT NOT NULL,
|
||||||
|
TotalTokens INT NOT NULL,
|
||||||
|
Model NVARCHAR(100),
|
||||||
|
CreatedAt DATETIME2 NOT NULL,
|
||||||
|
ResponseTimeMs BIGINT,
|
||||||
|
CONSTRAINT FK_DailyReports_Devices FOREIGN KEY (DeviceId)
|
||||||
|
REFERENCES Devices(Id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT UQ_DailyReports_DeviceDate UNIQUE (DeviceId, PersianDate)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## نکات مهم
|
||||||
|
|
||||||
|
1. **یکتایی گزارش:** برای هر دستگاه و تاریخ، فقط یک گزارش ذخیره میشود (UNIQUE constraint)
|
||||||
|
2. **کش خودکار:** سیستم به طور خودکار از گزارشهای قبلی استفاده میکند
|
||||||
|
3. **حذف cascade:** با حذف دستگاه، تمام گزارشهای آن نیز حذف میشوند
|
||||||
|
4. **زمان ایران:** زمانها در API به timezone ایران (UTC+3:30) تبدیل میشوند
|
||||||
|
5. **خطاهای لاگ:** تمام خطاها و عملیات در لاگ سیستم ثبت میشوند
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
|
برای اعمال تغییرات دیتابیس، migration زیر را اجرا کنید:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet ef database update --project GreenHome.Infrastructure --startup-project GreenHome.Api
|
||||||
|
```
|
||||||
|
|
||||||
|
یا به صورت خودکار در startup برنامه اعمال میشود.
|
||||||
|
|
||||||
358
src/DEEPSEEK_INTEGRATION.md
Normal file
358
src/DEEPSEEK_INTEGRATION.md
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
# 🎉 سرویس DeepSeek با موفقیت به پروژه GreenHome اضافه شد!
|
||||||
|
|
||||||
|
## ✅ کارهای انجام شده
|
||||||
|
|
||||||
|
### 1. پروژه جدید: GreenHome.AI.DeepSeek
|
||||||
|
یک کتابخانه کامل و مستقل برای اتصال به API DeepSeek ایجاد شد.
|
||||||
|
|
||||||
|
**فایلهای ایجاد شده:**
|
||||||
|
- ✅ `IDeepSeekService.cs` - Interface سرویس
|
||||||
|
- ✅ `DeepSeekService.cs` - پیادهسازی با HttpClient
|
||||||
|
- ✅ `DeepSeekOptions.cs` - کلاس تنظیمات
|
||||||
|
- ✅ `Models.cs` - مدلهای Request/Response
|
||||||
|
- ✅ `ServiceCollectionExtensions.cs` - Dependency Injection
|
||||||
|
|
||||||
|
**مستندات:**
|
||||||
|
- 📚 `README.md` - مستندات کامل فارسی
|
||||||
|
- 📖 `USAGE_FA.md` - راهنمای استفاده
|
||||||
|
- ⚡ `QUICKSTART.md` - راهنمای سریع شروع
|
||||||
|
- 📋 `SUMMARY.md` - خلاصه پروژه
|
||||||
|
|
||||||
|
### 2. Controller جدید: AIController
|
||||||
|
یک API Controller با 3 endpoint اصلی:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/ai/ask - پرسیدن سوال ساده
|
||||||
|
POST /api/ai/chat - چت پیشرفته با تاریخچه
|
||||||
|
POST /api/ai/suggest - دریافت پیشنهادات برای خانه هوشمند
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. تنظیمات
|
||||||
|
|
||||||
|
**Program.cs:**
|
||||||
|
```csharp
|
||||||
|
using GreenHome.AI.DeepSeek;
|
||||||
|
// ...
|
||||||
|
builder.Services.AddDeepSeek(builder.Configuration);
|
||||||
|
```
|
||||||
|
|
||||||
|
**appsettings.json:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DeepSeek": {
|
||||||
|
"BaseUrl": "https://api.deepseek.com",
|
||||||
|
"ApiKey": "YOUR_DEEPSEEK_API_KEY_HERE",
|
||||||
|
"DefaultModel": "deepseek-chat",
|
||||||
|
"DefaultTemperature": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 قابلیتها
|
||||||
|
|
||||||
|
✅ **اتصال به API رسمی DeepSeek**
|
||||||
|
- پشتیبانی کامل از Chat Completion API
|
||||||
|
- سازگار با استاندارد OpenAI
|
||||||
|
|
||||||
|
✅ **دو روش استفاده**
|
||||||
|
- `AskSimpleAsync()` - برای سوالات ساده
|
||||||
|
- `AskAsync()` - برای چت پیشرفته با تاریخچه
|
||||||
|
|
||||||
|
✅ **پیکربندی آسان**
|
||||||
|
- Configuration از appsettings.json
|
||||||
|
- پشتیبانی از User Secrets (Development)
|
||||||
|
- پشتیبانی از Environment Variables (Production)
|
||||||
|
|
||||||
|
✅ **امکانات پیشرفته**
|
||||||
|
- تنظیم Temperature (خلاقیت AI)
|
||||||
|
- تنظیم MaxTokens (طول پاسخ)
|
||||||
|
- انتخاب Model
|
||||||
|
- System Prompt برای زمینهسازی
|
||||||
|
|
||||||
|
✅ **Production Ready**
|
||||||
|
- Logging کامل
|
||||||
|
- مدیریت خطا
|
||||||
|
- HttpClient Factory
|
||||||
|
- Dependency Injection
|
||||||
|
- Timeout Management
|
||||||
|
|
||||||
|
## 📖 نحوه استفاده
|
||||||
|
|
||||||
|
### در Controller:
|
||||||
|
```csharp
|
||||||
|
public class MyController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService _ai;
|
||||||
|
|
||||||
|
public MyController(IDeepSeekService ai)
|
||||||
|
{
|
||||||
|
_ai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("analyze")]
|
||||||
|
public async Task<IActionResult> AnalyzeData(string data)
|
||||||
|
{
|
||||||
|
var result = await _ai.AskSimpleAsync(
|
||||||
|
$"تحلیل کن: {data}",
|
||||||
|
"شما یک متخصص خانه هوشمند هستید"
|
||||||
|
);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### در Service:
|
||||||
|
```csharp
|
||||||
|
public class SmartHomeService
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService _ai;
|
||||||
|
|
||||||
|
public SmartHomeService(IDeepSeekService ai)
|
||||||
|
{
|
||||||
|
_ai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetSuggestion(double temp, int humidity)
|
||||||
|
{
|
||||||
|
return await _ai.AskSimpleAsync(
|
||||||
|
$"دمای {temp}°C و رطوبت {humidity}% داریم. چه کنیم؟"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 شروع کار
|
||||||
|
|
||||||
|
### گام 1: دریافت API Key
|
||||||
|
1. به https://platform.deepseek.com بروید
|
||||||
|
2. ثبتنام کنید
|
||||||
|
3. API Key بسازید
|
||||||
|
|
||||||
|
### گام 2: تنظیم API Key
|
||||||
|
```bash
|
||||||
|
# Development (User Secrets)
|
||||||
|
dotnet user-secrets set "DeepSeek:ApiKey" "YOUR_KEY_HERE"
|
||||||
|
|
||||||
|
# Production (Environment Variable)
|
||||||
|
export DeepSeek__ApiKey="YOUR_KEY_HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
### گام 3: اجرا و تست
|
||||||
|
```bash
|
||||||
|
cd GreenHome.Api
|
||||||
|
dotnet run
|
||||||
|
|
||||||
|
# تست با curl
|
||||||
|
curl -X POST http://localhost:5000/api/ai/ask \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"question":"سلام! کار میکنی؟"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Swagger UI
|
||||||
|
بعد از اجرا، به آدرس زیر بروید:
|
||||||
|
```
|
||||||
|
http://localhost:5000/swagger
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌟 مثالهای کاربردی
|
||||||
|
|
||||||
|
### 1. تحلیل سنسور
|
||||||
|
```csharp
|
||||||
|
var sensorData = $@"
|
||||||
|
دمای اتاق خواب: {bedroom.Temperature}°C
|
||||||
|
رطوبت: {bedroom.Humidity}%
|
||||||
|
کیفیت هوا: {airQuality}
|
||||||
|
نور: {lightLevel} لوکس
|
||||||
|
";
|
||||||
|
|
||||||
|
var analysis = await _ai.AskSimpleAsync(
|
||||||
|
$"تحلیل کن و پیشنهاد بده:\n{sensorData}",
|
||||||
|
"شما یک متخصص خانه هوشمند هستید"
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. دستیار صوتی
|
||||||
|
```csharp
|
||||||
|
public async Task<string> ProcessVoiceCommand(string command)
|
||||||
|
{
|
||||||
|
var response = await _ai.AskSimpleAsync(
|
||||||
|
command,
|
||||||
|
"شما دستیار صوتی خانه هوشمند هستید. پاسخ کوتاه و مفید بده."
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. چت با حافظه
|
||||||
|
```csharp
|
||||||
|
var conversation = new List<ChatMessage>
|
||||||
|
{
|
||||||
|
new() { Role = "system", Content = "شما دستیار خانه هوشمند هستید" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// اضافه کردن تاریخچه از database
|
||||||
|
foreach (var msg in history)
|
||||||
|
{
|
||||||
|
conversation.Add(new ChatMessage
|
||||||
|
{
|
||||||
|
Role = msg.Role,
|
||||||
|
Content = msg.Content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// پیام جدید کاربر
|
||||||
|
conversation.Add(new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "user",
|
||||||
|
Content = userMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await _ai.AskAsync(new ChatRequest
|
||||||
|
{
|
||||||
|
Messages = conversation
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. هشدار هوشمند
|
||||||
|
```csharp
|
||||||
|
public async Task<string> GenerateAlert(TelemetryRecord record)
|
||||||
|
{
|
||||||
|
if (record.Temperature > 30)
|
||||||
|
{
|
||||||
|
return await _ai.AskSimpleAsync(
|
||||||
|
$"دمای {record.Temperature} درجه است. چه هشداری بدهیم؟",
|
||||||
|
"پیام هشدار کوتاه و واضح بنویس"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💡 نکات مهم
|
||||||
|
|
||||||
|
### امنیت
|
||||||
|
⚠️ **هرگز API Key را در Git commit نکنید!**
|
||||||
|
- از User Secrets در Development
|
||||||
|
- از Environment Variables در Production
|
||||||
|
|
||||||
|
### هزینه
|
||||||
|
💰 **هر درخواست هزینه دارد**
|
||||||
|
- بر اساس تعداد توکن
|
||||||
|
- پاسخهای مشابه را Cache کنید
|
||||||
|
- MaxTokens را محدود کنید
|
||||||
|
|
||||||
|
### عملکرد
|
||||||
|
⚡ **بهینهسازی**
|
||||||
|
- درخواستهای طولانی = زمان بیشتر
|
||||||
|
- Temperature پایینتر = سریعتر
|
||||||
|
- Cache برای سوالات تکراری
|
||||||
|
|
||||||
|
## 🐛 عیبیابی
|
||||||
|
|
||||||
|
| خطا | دلیل | راه حل |
|
||||||
|
|-----|------|--------|
|
||||||
|
| 401 Unauthorized | API Key نامعتبر | بررسی API Key |
|
||||||
|
| 429 Too Many Requests | درخواست زیاد | صبر کنید |
|
||||||
|
| Timeout | درخواست طولانی | MaxTokens را کاهش دهید |
|
||||||
|
| Connection Error | اینترنت قطع | بررسی اتصال |
|
||||||
|
|
||||||
|
## 📚 مستندات
|
||||||
|
|
||||||
|
### در پروژه:
|
||||||
|
- **کامل:** `GreenHome.AI.DeepSeek/README.md`
|
||||||
|
- **سریع:** `GreenHome.AI.DeepSeek/QUICKSTART.md`
|
||||||
|
- **استفاده:** `GreenHome.AI.DeepSeek/USAGE_FA.md`
|
||||||
|
- **خلاصه:** `GreenHome.AI.DeepSeek/SUMMARY.md`
|
||||||
|
|
||||||
|
### آنلاین:
|
||||||
|
- https://platform.deepseek.com/docs
|
||||||
|
- https://platform.deepseek.com/api-docs
|
||||||
|
- https://platform.deepseek.com/pricing
|
||||||
|
|
||||||
|
## 🎓 مثالهای بیشتر
|
||||||
|
|
||||||
|
### Automation Rule Generator
|
||||||
|
```csharp
|
||||||
|
public async Task<string> GenerateAutomationRule(string description)
|
||||||
|
{
|
||||||
|
var prompt = $@"
|
||||||
|
یک قانون اتوماسیون بساز:
|
||||||
|
{description}
|
||||||
|
|
||||||
|
فرمت خروجی JSON:
|
||||||
|
{{
|
||||||
|
""trigger"": ""..."",
|
||||||
|
""condition"": ""..."",
|
||||||
|
""action"": ""...""
|
||||||
|
}}
|
||||||
|
";
|
||||||
|
|
||||||
|
return await _ai.AskSimpleAsync(prompt);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Energy Optimization
|
||||||
|
```csharp
|
||||||
|
public async Task<EnergyReport> AnalyzeEnergyUsage(EnergyData data)
|
||||||
|
{
|
||||||
|
var analysis = await _ai.AskSimpleAsync(
|
||||||
|
$"مصرف برق: {data.PowerUsage}W، روشنایی: {data.LightCount}، کولر: {data.ACStatus}. چطور بهینه کنیم?",
|
||||||
|
"شما متخصص صرفهجویی انرژی هستید"
|
||||||
|
);
|
||||||
|
|
||||||
|
return ParseEnergyReport(analysis);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Natural Language Control
|
||||||
|
```csharp
|
||||||
|
public async Task<DeviceCommand> ParseCommand(string text)
|
||||||
|
{
|
||||||
|
var json = await _ai.AskSimpleAsync(
|
||||||
|
$@"این دستور را به JSON تبدیل کن: ""{text}""
|
||||||
|
فرمت: {{""device"": ""..."", ""action"": ""..."", ""value"": ""...""}}",
|
||||||
|
"فقط JSON خروجی بده، توضیح ندهید"
|
||||||
|
);
|
||||||
|
|
||||||
|
return JsonSerializer.Deserialize<DeviceCommand>(json);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✨ امکانات آینده
|
||||||
|
|
||||||
|
بعداً میتوانید اضافه کنید:
|
||||||
|
- [ ] Streaming Response (real-time)
|
||||||
|
- [ ] Function Calling (control devices)
|
||||||
|
- [ ] Image Analysis (camera feeds)
|
||||||
|
- [ ] Voice Integration
|
||||||
|
- [ ] Multi-language Support
|
||||||
|
- [ ] Context Memory in Database
|
||||||
|
- [ ] Rate Limiting
|
||||||
|
- [ ] Response Caching
|
||||||
|
- [ ] Analytics & Monitoring
|
||||||
|
|
||||||
|
## 🤝 مشارکت
|
||||||
|
|
||||||
|
برای گزارش مشکل یا پیشنهاد:
|
||||||
|
1. Issue در GitHub بسازید
|
||||||
|
2. یا تغییرات را Pull Request کنید
|
||||||
|
|
||||||
|
## 📄 لایسنس
|
||||||
|
|
||||||
|
این پروژه تحت لایسنس MIT است.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎉 تمام! آماده استفاده است!
|
||||||
|
|
||||||
|
حالا میتوانید:
|
||||||
|
1. ✅ API Key بگیرید
|
||||||
|
2. ✅ در appsettings قرار دهید
|
||||||
|
3. ✅ برنامه را اجرا کنید
|
||||||
|
4. ✅ از AI در پروژه استفاده کنید
|
||||||
|
|
||||||
|
**موفق باشید! 🚀**
|
||||||
|
|
||||||
243
src/DEVICE_TOKEN_API.md
Normal file
243
src/DEVICE_TOKEN_API.md
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
# API مدیریت توکن و تنظیمات دستگاه
|
||||||
|
|
||||||
|
این سند توضیح دهنده API های جدید اضافه شده برای مدیریت توکن و تنظیمات دستگاه است.
|
||||||
|
|
||||||
|
## تغییرات در مدل داده
|
||||||
|
|
||||||
|
### فیلدهای جدید در `DeviceSettings`
|
||||||
|
|
||||||
|
1. **UploadIntervalMin** (int): فاصله زمانی آپلود داده به دقیقه (پیشفرض: 5)
|
||||||
|
2. **DevicePhoneNumber** (string): شماره تلفن دستگاه
|
||||||
|
3. **SimCardType** (enum, nullable): نوع سیمکارت (همراه اول/ایرانسل/رایتل)
|
||||||
|
4. **TokenCode** (string, nullable): کد توکن 5 رقمی
|
||||||
|
5. **VerificationCode** (string, nullable): کد تایید 5 رقمی
|
||||||
|
6. **TokenExpiresAt** (DateTime, nullable): تاریخ انقضای توکن
|
||||||
|
|
||||||
|
### Enum نوع سیمکارت
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public enum SimCardType
|
||||||
|
{
|
||||||
|
Hamrahe_Aval = 1, // همراه اول
|
||||||
|
Irancell = 2, // ایرانسل
|
||||||
|
Rightel = 3 // رایتل
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### 1. دریافت فاصله زمانی آپلود
|
||||||
|
|
||||||
|
**GET** `/api/DeviceToken/upload-interval`
|
||||||
|
|
||||||
|
دریافت مقدار `UPLOAD_INTERVAL_MIN` بر اساس شناسه دستگاه یا شماره تلفن.
|
||||||
|
|
||||||
|
#### پارامترها (Query String)
|
||||||
|
|
||||||
|
- `deviceId` (int, optional): شناسه دستگاه
|
||||||
|
- `devicePhoneNumber` (string, optional): شماره تلفن دستگاه
|
||||||
|
|
||||||
|
**نکته:** حداقل یکی از پارامترها باید ارسال شود.
|
||||||
|
|
||||||
|
#### مثال درخواست
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/DeviceToken/upload-interval?devicePhoneNumber=09123456789
|
||||||
|
```
|
||||||
|
|
||||||
|
#### پاسخ موفق
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": null,
|
||||||
|
"uploadIntervalMin": 5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### پاسخ خطا
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"message": "دستگاه یافت نشد",
|
||||||
|
"uploadIntervalMin": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. درخواست توکن دستگاه
|
||||||
|
|
||||||
|
**POST** `/api/DeviceToken/request-token`
|
||||||
|
|
||||||
|
تولید کد توکن 5 رقمی و ارسال آن از طریق پیامک به شماره دستگاه.
|
||||||
|
|
||||||
|
#### بدنه درخواست (JSON)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"devicePhoneNumber": "09123456789"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مثال درخواست
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /api/DeviceToken/request-token
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"devicePhoneNumber": "09123456789"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### پاسخ موفق
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "کد تایید با موفقیت ارسال شد",
|
||||||
|
"tokenCode": "12345"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**نکته:** پیامک حاوی کد توکن به شماره مشخص شده ارسال میشود. کد دارای اعتبار 10 دقیقه است.
|
||||||
|
|
||||||
|
#### محاسبه کد تایید
|
||||||
|
|
||||||
|
کد تایید بر اساس فرمول زیر محاسبه میشود:
|
||||||
|
|
||||||
|
```
|
||||||
|
VerificationCode = (TokenCode × 7 + 12345) % 100000
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. تایید توکن دستگاه
|
||||||
|
|
||||||
|
**POST** `/api/DeviceToken/verify-token`
|
||||||
|
|
||||||
|
تایید کد تایید و ارسال تنظیمات کدشده دستگاه از طریق پیامک.
|
||||||
|
|
||||||
|
#### بدنه درخواست (JSON)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"devicePhoneNumber": "09123456789",
|
||||||
|
"verificationCode": "98765"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مثال درخواست
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /api/DeviceToken/verify-token
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"devicePhoneNumber": "09123456789",
|
||||||
|
"verificationCode": "98765"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### پاسخ موفق
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "تنظیمات با موفقیت ارسال شد",
|
||||||
|
"encodedSettings": "RGV2aWNlMDF8NQ=="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**نکته:** تنظیمات به صورت کدشده Base64 ارسال میشود. فرمت قبل از کدگذاری: `{DeviceName}|{UploadIntervalMin}`
|
||||||
|
|
||||||
|
#### پاسخ خطا
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"message": "کد تایید نادرست است",
|
||||||
|
"encodedSettings": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. بروزرسانی تنظیمات دستگاه
|
||||||
|
|
||||||
|
**PUT** `/api/DeviceSettings`
|
||||||
|
|
||||||
|
API موجود که حالا فیلدهای جدید را نیز پشتیبانی میکند.
|
||||||
|
|
||||||
|
#### بدنه درخواست (JSON)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"deviceId": 1,
|
||||||
|
"province": "تهران",
|
||||||
|
"city": "تهران",
|
||||||
|
"productType": "گلخانه",
|
||||||
|
"uploadIntervalMin": 5,
|
||||||
|
"devicePhoneNumber": "09123456789",
|
||||||
|
"simCardType": 1,
|
||||||
|
"minimumSmsIntervalMinutes": 15,
|
||||||
|
"minimumCallIntervalMinutes": 60
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## فلوی کاری (Workflow)
|
||||||
|
|
||||||
|
### سناریو: دریافت تنظیمات دستگاه
|
||||||
|
|
||||||
|
1. **دستگاه درخواست توکن میکند:**
|
||||||
|
```http
|
||||||
|
POST /api/DeviceToken/request-token
|
||||||
|
Body: { "devicePhoneNumber": "09123456789" }
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **سرور کد توکن تولید و ارسال میکند:**
|
||||||
|
- کد توکن 5 رقمی: مثلاً `12345`
|
||||||
|
- کد تایید محاسبه شده: `(12345 × 7 + 12345) % 100000 = 98760`
|
||||||
|
- پیامک حاوی کد توکن به شماره دستگاه ارسال میشود
|
||||||
|
|
||||||
|
3. **دستگاه کد تایید را محاسبه و ارسال میکند:**
|
||||||
|
```http
|
||||||
|
POST /api/DeviceToken/verify-token
|
||||||
|
Body: {
|
||||||
|
"devicePhoneNumber": "09123456789",
|
||||||
|
"verificationCode": "98760"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **سرور تنظیمات کدشده را ارسال میکند:**
|
||||||
|
- تنظیمات: `Device01|5`
|
||||||
|
- Base64: `RGV2aWNlMDF8NQ==`
|
||||||
|
- پیامک حاوی تنظیمات کدشده به شماره دستگاه ارسال میشود
|
||||||
|
|
||||||
|
5. **دستگاه تنظیمات را decode کرده و اعمال میکند**
|
||||||
|
|
||||||
|
## نکات امنیتی
|
||||||
|
|
||||||
|
1. کد توکن فقط 10 دقیقه اعتبار دارد
|
||||||
|
2. پس از تایید موفق، کدهای توکن و تایید از دیتابیس پاک میشوند
|
||||||
|
3. کدگذاری Base64 یک کدگذاری ساده است و برای امنیت بیشتر میتوان از روشهای پیچیدهتر استفاده کرد
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
|
Migration با نام `AddDeviceTokenAndPhoneFields` ایجاد و به دیتابیس اعمال شده است.
|
||||||
|
|
||||||
|
برای اعمال دستی (در صورت نیاز):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet ef database update --project GreenHome.Infrastructure --startup-project GreenHome.Api
|
||||||
|
```
|
||||||
|
|
||||||
|
## تست API ها
|
||||||
|
|
||||||
|
میتوانید از Swagger UI (که در حالت Development در `/scalar/v1` در دسترس است) برای تست API ها استفاده کنید.
|
||||||
|
|
||||||
|
یا از ابزارهایی مانند Postman/Insomnia با استفاده از نمونههای بالا.
|
||||||
|
|
||||||
33
src/GreenHome.AI.DeepSeek/DeepSeekOptions.cs
Normal file
33
src/GreenHome.AI.DeepSeek/DeepSeekOptions.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
namespace GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configuration options for DeepSeek AI service
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DeepSeekOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DeepSeek API base URL
|
||||||
|
/// </summary>
|
||||||
|
public string BaseUrl { get; set; } = "https://api.deepseek.com";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DeepSeek API key (required)
|
||||||
|
/// </summary>
|
||||||
|
public required string ApiKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default model to use
|
||||||
|
/// </summary>
|
||||||
|
public string DefaultModel { get; set; } = "deepseek-chat";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default temperature for responses (0-2)
|
||||||
|
/// </summary>
|
||||||
|
public double DefaultTemperature { get; set; } = 1.0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default maximum tokens for responses
|
||||||
|
/// </summary>
|
||||||
|
public int? DefaultMaxTokens { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
124
src/GreenHome.AI.DeepSeek/DeepSeekService.cs
Normal file
124
src/GreenHome.AI.DeepSeek/DeepSeekService.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DeepSeek AI service implementation
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DeepSeekService : IDeepSeekService
|
||||||
|
{
|
||||||
|
private readonly HttpClient httpClient;
|
||||||
|
private readonly DeepSeekOptions options;
|
||||||
|
private readonly ILogger<DeepSeekService> logger;
|
||||||
|
|
||||||
|
public DeepSeekService(
|
||||||
|
HttpClient httpClient,
|
||||||
|
DeepSeekOptions options,
|
||||||
|
ILogger<DeepSeekService> logger)
|
||||||
|
{
|
||||||
|
this.httpClient = httpClient;
|
||||||
|
this.options = options;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ChatResponse?> AskAsync(
|
||||||
|
ChatRequest request,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Set defaults if not provided
|
||||||
|
if (string.IsNullOrEmpty(request.Model))
|
||||||
|
{
|
||||||
|
request.Model = options.DefaultModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request.Temperature.HasValue)
|
||||||
|
{
|
||||||
|
request.Temperature = options.DefaultTemperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request.MaxTokens.HasValue && options.DefaultMaxTokens.HasValue)
|
||||||
|
{
|
||||||
|
request.MaxTokens = options.DefaultMaxTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("Sending chat request to DeepSeek AI with {MessageCount} messages",
|
||||||
|
request.Messages.Count);
|
||||||
|
|
||||||
|
var response = await httpClient.PostAsJsonAsync(
|
||||||
|
"v1/chat/completions",
|
||||||
|
request,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var result = await response.Content.ReadFromJsonAsync<ChatResponse>(
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
|
||||||
|
logger.LogInformation("Received response from DeepSeek AI, used {TotalTokens} tokens",
|
||||||
|
result?.Usage?.TotalTokens ?? 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "HTTP error while communicating with DeepSeek AI");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Unexpected error while calling DeepSeek AI");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string?> AskSimpleAsync(
|
||||||
|
string question,
|
||||||
|
string? systemPrompt = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var messages = new List<ChatMessage>();
|
||||||
|
|
||||||
|
// Add system prompt if provided
|
||||||
|
if (!string.IsNullOrWhiteSpace(systemPrompt))
|
||||||
|
{
|
||||||
|
messages.Add(new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "system",
|
||||||
|
Content = systemPrompt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add user question
|
||||||
|
messages.Add(new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "user",
|
||||||
|
Content = question
|
||||||
|
});
|
||||||
|
|
||||||
|
var request = new ChatRequest
|
||||||
|
{
|
||||||
|
Model = options.DefaultModel,
|
||||||
|
Messages = messages,
|
||||||
|
Temperature = options.DefaultTemperature,
|
||||||
|
MaxTokens = options.DefaultMaxTokens
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await AskAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
// Extract the text content from the response
|
||||||
|
return response?.Choices?.FirstOrDefault()?.Message?.Content;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error in AskSimpleAsync for question: {Question}", question);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
15
src/GreenHome.AI.DeepSeek/GreenHome.AI.DeepSeek.csproj
Normal file
15
src/GreenHome.AI.DeepSeek/GreenHome.AI.DeepSeek.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
25
src/GreenHome.AI.DeepSeek/IDeepSeekService.cs
Normal file
25
src/GreenHome.AI.DeepSeek/IDeepSeekService.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for DeepSeek AI service
|
||||||
|
/// </summary>
|
||||||
|
public interface IDeepSeekService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a chat request to DeepSeek AI and gets a response
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">The chat request containing messages</param>
|
||||||
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
|
/// <returns>The AI response</returns>
|
||||||
|
Task<ChatResponse?> AskAsync(ChatRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a simple question to DeepSeek AI and gets a text response
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="question">The question to ask</param>
|
||||||
|
/// <param name="systemPrompt">Optional system prompt to set context</param>
|
||||||
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
|
/// <returns>The AI response text</returns>
|
||||||
|
Task<string?> AskSimpleAsync(string question, string? systemPrompt = null, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
|
||||||
129
src/GreenHome.AI.DeepSeek/Models.cs
Normal file
129
src/GreenHome.AI.DeepSeek/Models.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request to ask a question to DeepSeek AI
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ChatRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The model to use (default: deepseek-chat)
|
||||||
|
/// </summary>
|
||||||
|
public string Model { get; set; } = "deepseek-chat";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The messages to send to the AI
|
||||||
|
/// </summary>
|
||||||
|
public required List<ChatMessage> Messages { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Temperature for response randomness (0-2, default: 1)
|
||||||
|
/// </summary>
|
||||||
|
public double? Temperature { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum tokens in the response
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("max_tokens")]
|
||||||
|
public int? MaxTokens { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A single message in the chat
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ChatMessage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Role of the message sender (system, user, or assistant)
|
||||||
|
/// </summary>
|
||||||
|
public required string Role { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Content of the message
|
||||||
|
/// </summary>
|
||||||
|
public required string Content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Response from DeepSeek AI
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ChatResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unique ID for the chat completion
|
||||||
|
/// </summary>
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Object type (e.g., "chat.completion")
|
||||||
|
/// </summary>
|
||||||
|
public string? Object { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unix timestamp of when the completion was created
|
||||||
|
/// </summary>
|
||||||
|
public long Created { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The model used for the completion
|
||||||
|
/// </summary>
|
||||||
|
public string? Model { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The completion choices
|
||||||
|
/// </summary>
|
||||||
|
public List<ChatChoice>? Choices { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Usage statistics for the request
|
||||||
|
/// </summary>
|
||||||
|
public ChatUsage? Usage { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A choice in the chat completion response
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ChatChoice
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Index of the choice
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message from the AI
|
||||||
|
/// </summary>
|
||||||
|
public ChatMessage? Message { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reason for completion finish
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("finish_reason")]
|
||||||
|
public string? FinishReason { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Token usage statistics
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ChatUsage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Number of tokens in the prompt
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("prompt_tokens")]
|
||||||
|
public int PromptTokens { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of tokens in the completion
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("completion_tokens")]
|
||||||
|
public int CompletionTokens { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total number of tokens used
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("total_tokens")]
|
||||||
|
public int TotalTokens { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
126
src/GreenHome.AI.DeepSeek/QUICKSTART.md
Normal file
126
src/GreenHome.AI.DeepSeek/QUICKSTART.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# 🚀 راهنمای سریع شروع - 5 دقیقه!
|
||||||
|
|
||||||
|
## مرحله 1: دریافت API Key (2 دقیقه)
|
||||||
|
|
||||||
|
1. به https://platform.deepseek.com بروید
|
||||||
|
2. روی "Sign Up" کلیک کنید (یا Login اگر قبلاً ثبتنام کردهاید)
|
||||||
|
3. وارد Dashboard شوید
|
||||||
|
4. از منوی سمت چپ، گزینه "API Keys" را انتخاب کنید
|
||||||
|
5. روی "Create API Key" کلیک کنید
|
||||||
|
6. یک نام برای کلید انتخاب کنید (مثلاً "GreenHome")
|
||||||
|
7. کلید را کپی کنید ⚠️ (فقط یک بار نمایش داده میشود!)
|
||||||
|
|
||||||
|
## مرحله 2: تنظیم API Key (1 دقیقه)
|
||||||
|
|
||||||
|
فایل `appsettings.json` را باز کنید و API Key را جایگزین کنید:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DeepSeek": {
|
||||||
|
"ApiKey": "اینجا-کلید-خود-را-بگذارید"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## مرحله 3: اجرای برنامه (1 دقیقه)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd GreenHome.Api
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
## مرحله 4: تست API (1 دقیقه)
|
||||||
|
|
||||||
|
### با Swagger:
|
||||||
|
1. مرورگر را باز کنید: http://localhost:5000/swagger
|
||||||
|
2. endpoint `/api/ai/ask` را باز کنید
|
||||||
|
3. روی "Try it out" کلیک کنید
|
||||||
|
4. این را در Body بگذارید:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "سلام! آیا کار میکنی؟"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
5. روی "Execute" کلیک کنید
|
||||||
|
6. پاسخ را ببینید! ✅
|
||||||
|
|
||||||
|
### با Curl:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5000/api/ai/ask \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"question":"سلام! آیا کار میکنی؟"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### با Postman:
|
||||||
|
1. Postman را باز کنید
|
||||||
|
2. یک درخواست POST جدید بسازید
|
||||||
|
3. URL: `http://localhost:5000/api/ai/ask`
|
||||||
|
4. Headers: `Content-Type: application/json`
|
||||||
|
5. Body (raw JSON):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "سلام! آیا کار میکنی؟"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
6. Send را بزنید!
|
||||||
|
|
||||||
|
## 🎉 تبریک! شما آمادهاید!
|
||||||
|
|
||||||
|
اکنون میتوانید از AI در پروژه خود استفاده کنید.
|
||||||
|
|
||||||
|
## مثالهای آماده برای تست:
|
||||||
|
|
||||||
|
### 1. سوال درباره خانه هوشمند:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "چگونه میتوانم مصرف برق خانه را کاهش دهم؟"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. دریافت پیشنهاد:
|
||||||
|
**Endpoint:** POST `/api/ai/suggest`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceContext": "دمای اتاق: 28 درجه، رطوبت: 65%، ساعت: 14:00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. سوال با زمینه خاص:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "بهترین دمای کولر برای خواب چیست؟",
|
||||||
|
"systemPrompt": "شما یک متخصص خانه هوشمند و بهینهسازی انرژی هستید."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ❓ مشکل دارید؟
|
||||||
|
|
||||||
|
### خطا: 401 Unauthorized
|
||||||
|
- ✅ بررسی کنید API Key را صحیح کپی کردهاید
|
||||||
|
- ✅ فاصله اضافی ندارد
|
||||||
|
- ✅ در appsettings.json به درستی قرار دارد
|
||||||
|
|
||||||
|
### خطا: Connection Refused
|
||||||
|
- ✅ مطمئن شوید برنامه اجرا شده است (`dotnet run`)
|
||||||
|
- ✅ پورت صحیح است (معمولاً 5000 یا 5001)
|
||||||
|
|
||||||
|
### خطا: 429 Too Many Requests
|
||||||
|
- ✅ کمی صبر کنید (1-2 دقیقه)
|
||||||
|
- ✅ تعداد درخواستهای شما زیاد بوده است
|
||||||
|
|
||||||
|
## 📚 مستندات بیشتر
|
||||||
|
|
||||||
|
- مستندات کامل: [README.md](README.md)
|
||||||
|
- راهنمای استفاده: [USAGE_FA.md](USAGE_FA.md)
|
||||||
|
- خلاصه پروژه: [SUMMARY.md](SUMMARY.md)
|
||||||
|
|
||||||
|
## 🎯 مرحله بعدی
|
||||||
|
|
||||||
|
اکنون میتوانید:
|
||||||
|
1. ✅ از AI در Controller های خود استفاده کنید
|
||||||
|
2. ✅ پیشنهادات هوشمند برای کاربران ارائه دهید
|
||||||
|
3. ✅ تحلیل دادههای سنسورها را انجام دهید
|
||||||
|
4. ✅ چتبات هوشمند بسازید
|
||||||
|
|
||||||
|
موفق باشید! 🚀
|
||||||
|
|
||||||
399
src/GreenHome.AI.DeepSeek/README.md
Normal file
399
src/GreenHome.AI.DeepSeek/README.md
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
# GreenHome.AI.DeepSeek
|
||||||
|
|
||||||
|
سرویس هوش مصنوعی DeepSeek برای پروژه GreenHome
|
||||||
|
|
||||||
|
## درباره DeepSeek
|
||||||
|
|
||||||
|
DeepSeek یک مدل هوش مصنوعی پیشرفته است که میتوانید از آن برای:
|
||||||
|
- پاسخ به سوالات کاربران
|
||||||
|
- تحلیل دادههای خانه هوشمند
|
||||||
|
- ارائه پیشنهادات بهینهسازی
|
||||||
|
- تولید محتوای هوشمند
|
||||||
|
|
||||||
|
## نصب و راهاندازی
|
||||||
|
|
||||||
|
### 1. اضافه کردن Reference به پروژه
|
||||||
|
|
||||||
|
در فایل `.csproj` پروژه خود:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GreenHome.AI.DeepSeek\GreenHome.AI.DeepSeek.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. دریافت API Key
|
||||||
|
|
||||||
|
1. به وبسایت [DeepSeek](https://platform.deepseek.com/) بروید
|
||||||
|
2. ثبتنام کنید یا وارد حساب کاربری خود شوید
|
||||||
|
3. از بخش API Keys، یک کلید API جدید بسازید
|
||||||
|
4. کلید را کپی کنید (فقط یک بار نمایش داده میشود!)
|
||||||
|
|
||||||
|
### 3. ثبت سرویس در Program.cs
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
// روش 1: استفاده از Configuration (پیشنهادی)
|
||||||
|
builder.Services.AddDeepSeek(builder.Configuration);
|
||||||
|
|
||||||
|
// روش 2: استفاده از Configuration Section
|
||||||
|
builder.Services.AddDeepSeek(builder.Configuration.GetSection("DeepSeek"));
|
||||||
|
|
||||||
|
// روش 3: تنظیم دستی
|
||||||
|
builder.Services.AddDeepSeek(options =>
|
||||||
|
{
|
||||||
|
options.ApiKey = "YOUR_API_KEY_HERE";
|
||||||
|
options.BaseUrl = "https://api.deepseek.com";
|
||||||
|
options.DefaultModel = "deepseek-chat";
|
||||||
|
options.DefaultTemperature = 1.0;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. تنظیمات در appsettings.json
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DeepSeek": {
|
||||||
|
"BaseUrl": "https://api.deepseek.com",
|
||||||
|
"ApiKey": "YOUR_DEEPSEEK_API_KEY_HERE",
|
||||||
|
"DefaultModel": "deepseek-chat",
|
||||||
|
"DefaultTemperature": 1.0,
|
||||||
|
"DefaultMaxTokens": 2000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**نکته امنیتی:** هرگز API Key خود را در کد یا repository قرار ندهید! از Environment Variables یا User Secrets استفاده کنید.
|
||||||
|
|
||||||
|
#### استفاده از User Secrets (Development)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet user-secrets init
|
||||||
|
dotnet user-secrets set "DeepSeek:ApiKey" "YOUR_API_KEY_HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### استفاده از Environment Variables (Production)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DeepSeek__ApiKey="YOUR_API_KEY_HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
## استفاده در کنترلرها
|
||||||
|
|
||||||
|
### تزریق سرویس
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class AIController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService deepSeekService;
|
||||||
|
|
||||||
|
public AIController(IDeepSeekService deepSeekService)
|
||||||
|
{
|
||||||
|
this.deepSeekService = deepSeekService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### سوال ساده
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var response = await deepSeekService.AskSimpleAsync(
|
||||||
|
"چگونه میتوانم مصرف انرژی خانه را کاهش دهم؟"
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine(response);
|
||||||
|
```
|
||||||
|
|
||||||
|
### سوال با System Prompt
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var systemPrompt = "شما یک مشاور خانه هوشمند هستید.";
|
||||||
|
var question = "بهترین دمای کولر برای صرفهجویی انرژی چقدر است؟";
|
||||||
|
|
||||||
|
var response = await deepSeekService.AskSimpleAsync(question, systemPrompt);
|
||||||
|
```
|
||||||
|
|
||||||
|
### چت پیشرفته با تاریخچه
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var request = new ChatRequest
|
||||||
|
{
|
||||||
|
Model = "deepseek-chat",
|
||||||
|
Messages = new List<ChatMessage>
|
||||||
|
{
|
||||||
|
new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "system",
|
||||||
|
Content = "شما یک دستیار هوشمند خانه هوشمند هستید."
|
||||||
|
},
|
||||||
|
new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "user",
|
||||||
|
Content = "دمای فعلی 28 درجه است"
|
||||||
|
},
|
||||||
|
new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "assistant",
|
||||||
|
Content = "باشه، دمای فعلی خانه را دریافت کردم."
|
||||||
|
},
|
||||||
|
new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "user",
|
||||||
|
Content = "آیا باید کولر را روشن کنم؟"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Temperature = 0.7,
|
||||||
|
MaxTokens = 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await deepSeekService.AskAsync(request);
|
||||||
|
var answer = response?.Choices?.FirstOrDefault()?.Message?.Content;
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
سرویس شامل 3 endpoint اصلی است:
|
||||||
|
|
||||||
|
### 1. POST /api/ai/ask
|
||||||
|
پرسیدن یک سوال ساده
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "چگونه میتوانم دمای خانه را کنترل کنم؟",
|
||||||
|
"systemPrompt": "شما یک مشاور خانه هوشمند هستید."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "چگونه میتوانم دمای خانه را کنترل کنم؟",
|
||||||
|
"answer": "برای کنترل دمای خانه میتوانید از ترموستات هوشمند استفاده کنید...",
|
||||||
|
"timestamp": "2025-12-16T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. POST /api/ai/chat
|
||||||
|
چت پیشرفته با تاریخچه
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"model": "deepseek-chat",
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "شما یک دستیار هوشمند هستید."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "سلام"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature": 0.7,
|
||||||
|
"maxTokens": 2000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "chatcmpl-xxx",
|
||||||
|
"object": "chat.completion",
|
||||||
|
"created": 1702735200,
|
||||||
|
"model": "deepseek-chat",
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "سلام! چطور میتونم کمکتون کنم؟"
|
||||||
|
},
|
||||||
|
"finishReason": "stop"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"usage": {
|
||||||
|
"promptTokens": 20,
|
||||||
|
"completionTokens": 15,
|
||||||
|
"totalTokens": 35
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. POST /api/ai/suggest
|
||||||
|
دریافت پیشنهادات برای بهینهسازی خانه هوشمند
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceContext": "دمای اتاق: 28°C، رطوبت: 65%، ساعت: 14:00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"suggestions": "با توجه به دمای بالای 28 درجه، توصیه میشود کولر را روشن کنید...",
|
||||||
|
"timestamp": "2025-12-16T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## مثالهای کاربردی
|
||||||
|
|
||||||
|
### 1. تحلیل دادههای سنسور
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var deviceData = $@"
|
||||||
|
دمای اتاق خواب: {temperature}°C
|
||||||
|
رطوبت: {humidity}%
|
||||||
|
کیفیت هوا: {airQuality}
|
||||||
|
ساعت: {DateTime.Now:HH:mm}
|
||||||
|
";
|
||||||
|
|
||||||
|
var systemPrompt = "شما یک مشاور خانه هوشمند هستید که بر اساس دادههای سنسورها پیشنهاد میدهید.";
|
||||||
|
|
||||||
|
var response = await deepSeekService.AskSimpleAsync(
|
||||||
|
$"وضعیت خانه: {deviceData}\nچه کاری باید انجام دهم؟",
|
||||||
|
systemPrompt
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. پاسخ به سوالات کاربر
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[HttpPost("ask")]
|
||||||
|
public async Task<IActionResult> Ask([FromBody] string question)
|
||||||
|
{
|
||||||
|
var answer = await deepSeekService.AskSimpleAsync(question);
|
||||||
|
return Ok(new { question, answer });
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. دستیار هوشمند با حافظه
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// ذخیره تاریخچه در session یا database
|
||||||
|
var conversationHistory = GetConversationHistory(userId);
|
||||||
|
|
||||||
|
var request = new ChatRequest
|
||||||
|
{
|
||||||
|
Messages = conversationHistory.Select(m => new ChatMessage
|
||||||
|
{
|
||||||
|
Role = m.Role,
|
||||||
|
Content = m.Content
|
||||||
|
}).ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
// اضافه کردن پیام جدید کاربر
|
||||||
|
request.Messages.Add(new ChatMessage
|
||||||
|
{
|
||||||
|
Role = "user",
|
||||||
|
Content = userMessage
|
||||||
|
});
|
||||||
|
|
||||||
|
var response = await deepSeekService.AskAsync(request);
|
||||||
|
|
||||||
|
// ذخیره پاسخ در تاریخچه
|
||||||
|
SaveToHistory(userId, response);
|
||||||
|
```
|
||||||
|
|
||||||
|
## پارامترها
|
||||||
|
|
||||||
|
### Temperature
|
||||||
|
- **مقدار:** 0 تا 2
|
||||||
|
- **پیشفرض:** 1.0
|
||||||
|
- **توضیح:** هر چه عدد بالاتر باشد، پاسخها خلاقانهتر و تصادفیتر هستند
|
||||||
|
|
||||||
|
### MaxTokens
|
||||||
|
- **توضیح:** حداکثر تعداد توکن در پاسخ
|
||||||
|
- **توصیه:** برای پاسخهای کوتاه: 500، برای پاسخهای بلند: 2000
|
||||||
|
|
||||||
|
### Model
|
||||||
|
- **مقدار:** `deepseek-chat` (پیشفرض)
|
||||||
|
- **توضیح:** مدل مورد استفاده برای تولید پاسخ
|
||||||
|
|
||||||
|
## نکات مهم
|
||||||
|
|
||||||
|
1. **هزینه:** هر درخواست به DeepSeek بر اساس تعداد توکنهای استفاده شده هزینه دارد
|
||||||
|
2. **Rate Limiting:** محدودیت تعداد درخواست در واحد زمان را رعایت کنید
|
||||||
|
3. **Timeout:** درخواستهای AI ممکن است طولانی باشند (پیشفرض: 60 ثانیه)
|
||||||
|
4. **خطاها:** همیشه خطاها را مدیریت کنید و پیام مناسب به کاربر نمایش دهید
|
||||||
|
5. **امنیت:** API Key را محرمانه نگه دارید
|
||||||
|
|
||||||
|
## عیبیابی
|
||||||
|
|
||||||
|
### خطای 401 Unauthorized
|
||||||
|
- بررسی کنید که API Key صحیح است
|
||||||
|
- مطمئن شوید که در configuration به درستی تنظیم شده است
|
||||||
|
|
||||||
|
### خطای 429 Too Many Requests
|
||||||
|
- به محدودیت rate limit رسیدهاید
|
||||||
|
- کمی صبر کنید و دوباره تلاش کنید
|
||||||
|
|
||||||
|
### خطای Timeout
|
||||||
|
- درخواست خیلی طولانی است
|
||||||
|
- MaxTokens را کاهش دهید یا Timeout را افزایش دهید
|
||||||
|
|
||||||
|
## مثال کامل
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using GreenHome.AI.DeepSeek;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class SmartHomeAIController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService _ai;
|
||||||
|
private readonly ILogger<SmartHomeAIController> _logger;
|
||||||
|
|
||||||
|
public SmartHomeAIController(
|
||||||
|
IDeepSeekService ai,
|
||||||
|
ILogger<SmartHomeAIController> logger)
|
||||||
|
{
|
||||||
|
_ai = ai;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("analyze")]
|
||||||
|
public async Task<IActionResult> AnalyzeHome([FromBody] HomeData data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var prompt = $@"
|
||||||
|
دادههای خانه هوشمند:
|
||||||
|
- دمای داخل: {data.Temperature}°C
|
||||||
|
- رطوبت: {data.Humidity}%
|
||||||
|
- مصرف برق: {data.PowerUsage}W
|
||||||
|
- تعداد افراد: {data.OccupancyCount}
|
||||||
|
|
||||||
|
لطفاً تحلیل کامل ارائه دهید و پیشنهادات بهینهسازی بدهید.
|
||||||
|
";
|
||||||
|
|
||||||
|
var systemPrompt = "شما یک متخصص خانه هوشمند هستید.";
|
||||||
|
|
||||||
|
var analysis = await _ai.AskSimpleAsync(prompt, systemPrompt);
|
||||||
|
|
||||||
|
return Ok(new { analysis, timestamp = DateTime.UtcNow });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error analyzing home data");
|
||||||
|
return StatusCode(500, "خطا در تحلیل دادهها");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## منابع
|
||||||
|
|
||||||
|
- [DeepSeek Documentation](https://platform.deepseek.com/docs)
|
||||||
|
- [API Reference](https://platform.deepseek.com/api-docs)
|
||||||
|
- [Pricing](https://platform.deepseek.com/pricing)
|
||||||
|
|
||||||
|
## پشتیبانی
|
||||||
|
|
||||||
|
در صورت بروز مشکل، لطفاً یک Issue در GitHub ایجاد کنید.
|
||||||
|
|
||||||
200
src/GreenHome.AI.DeepSeek/SUMMARY.md
Normal file
200
src/GreenHome.AI.DeepSeek/SUMMARY.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# خلاصه سرویس DeepSeek برای GreenHome
|
||||||
|
|
||||||
|
## ✅ کارهای انجام شده
|
||||||
|
|
||||||
|
### 1. ساختار پروژه
|
||||||
|
- ✅ پروژه `GreenHome.AI.DeepSeek` ایجاد شد
|
||||||
|
- ✅ به Solution اضافه شد
|
||||||
|
- ✅ Reference در پروژه API افزوده شد
|
||||||
|
- ✅ بستههای NuGet نصب شدند
|
||||||
|
|
||||||
|
### 2. فایلهای ایجاد شده
|
||||||
|
|
||||||
|
#### Core Files:
|
||||||
|
- ✅ `IDeepSeekService.cs` - Interface سرویس
|
||||||
|
- ✅ `DeepSeekService.cs` - پیادهسازی سرویس
|
||||||
|
- ✅ `DeepSeekOptions.cs` - تنظیمات
|
||||||
|
- ✅ `Models.cs` - مدلهای درخواست و پاسخ
|
||||||
|
- ✅ `ServiceCollectionExtensions.cs` - ثبت سرویس در DI
|
||||||
|
|
||||||
|
#### API Controller:
|
||||||
|
- ✅ `AIController.cs` - 3 endpoint برای استفاده از AI
|
||||||
|
|
||||||
|
#### Documentation:
|
||||||
|
- ✅ `README.md` - مستندات کامل (فارسی)
|
||||||
|
- ✅ `USAGE_FA.md` - راهنمای سریع (فارسی)
|
||||||
|
- ✅ `SUMMARY.md` - این فایل
|
||||||
|
|
||||||
|
### 3. تنظیمات
|
||||||
|
|
||||||
|
#### Program.cs
|
||||||
|
```csharp
|
||||||
|
using GreenHome.AI.DeepSeek;
|
||||||
|
// ...
|
||||||
|
builder.Services.AddDeepSeek(builder.Configuration);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### appsettings.json
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DeepSeek": {
|
||||||
|
"BaseUrl": "https://api.deepseek.com",
|
||||||
|
"ApiKey": "YOUR_DEEPSEEK_API_KEY_HERE",
|
||||||
|
"DefaultModel": "deepseek-chat",
|
||||||
|
"DefaultTemperature": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 API Endpoints
|
||||||
|
|
||||||
|
### 1. POST /api/ai/ask
|
||||||
|
پرسیدن سوال ساده از AI
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "سوال شما",
|
||||||
|
"systemPrompt": "زمینه و کنتکست (اختیاری)"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. POST /api/ai/chat
|
||||||
|
چت پیشرفته با تاریخچه
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{"role": "system", "content": "..."},
|
||||||
|
{"role": "user", "content": "..."}
|
||||||
|
],
|
||||||
|
"temperature": 0.7,
|
||||||
|
"maxTokens": 2000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. POST /api/ai/suggest
|
||||||
|
دریافت پیشنهادات برای خانه هوشمند
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deviceContext": "دمای اتاق: 28°C، رطوبت: 65%"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 ویژگیها
|
||||||
|
|
||||||
|
- ✅ اتصال به API رسمی DeepSeek
|
||||||
|
- ✅ پشتیبانی از چت ساده و پیشرفته
|
||||||
|
- ✅ قابلیت تنظیم Temperature و MaxTokens
|
||||||
|
- ✅ Logging کامل
|
||||||
|
- ✅ مدیریت خطا
|
||||||
|
- ✅ استفاده از HttpClient Factory
|
||||||
|
- ✅ Dependency Injection
|
||||||
|
- ✅ Configuration از appsettings.json
|
||||||
|
- ✅ مستندات کامل فارسی
|
||||||
|
|
||||||
|
## 🚀 نحوه استفاده
|
||||||
|
|
||||||
|
### در Controller:
|
||||||
|
```csharp
|
||||||
|
public class MyController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService _ai;
|
||||||
|
|
||||||
|
public MyController(IDeepSeekService ai)
|
||||||
|
{
|
||||||
|
_ai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Ask(string question)
|
||||||
|
{
|
||||||
|
var answer = await _ai.AskSimpleAsync(question);
|
||||||
|
return Ok(answer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### در Service:
|
||||||
|
```csharp
|
||||||
|
public class MyService
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService _ai;
|
||||||
|
|
||||||
|
public MyService(IDeepSeekService ai)
|
||||||
|
{
|
||||||
|
_ai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetSuggestion(string context)
|
||||||
|
{
|
||||||
|
return await _ai.AskSimpleAsync(
|
||||||
|
$"پیشنهاد بده: {context}",
|
||||||
|
"شما یک مشاور خانه هوشمند هستید"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ پیشنیازها
|
||||||
|
|
||||||
|
1. دریافت API Key از https://platform.deepseek.com
|
||||||
|
2. قرار دادن API Key در appsettings.json
|
||||||
|
3. اطمینان از اتصال اینترنت
|
||||||
|
|
||||||
|
## ⚠️ نکات مهم
|
||||||
|
|
||||||
|
1. **امنیت:** API Key را در Git commit نکنید
|
||||||
|
2. **هزینه:** هر درخواست بر اساس توکن هزینه دارد
|
||||||
|
3. **محدودیت:** Rate limiting وجود دارد
|
||||||
|
4. **Timeout:** درخواستها ممکن است کند باشند (60 ثانیه)
|
||||||
|
|
||||||
|
## 🔧 عیبیابی
|
||||||
|
|
||||||
|
| خطا | دلیل | راه حل |
|
||||||
|
|-----|------|--------|
|
||||||
|
| 401 Unauthorized | API Key نامعتبر | بررسی API Key در appsettings.json |
|
||||||
|
| 429 Too Many Requests | تعداد درخواست زیاد | کمی صبر کنید (1-2 دقیقه) |
|
||||||
|
| Timeout | درخواست طولانی | MaxTokens را کاهش دهید |
|
||||||
|
|
||||||
|
## 📚 مستندات
|
||||||
|
|
||||||
|
- مستندات کامل: [README.md](README.md)
|
||||||
|
- راهنمای سریع: [USAGE_FA.md](USAGE_FA.md)
|
||||||
|
- وبسایت DeepSeek: https://platform.deepseek.com
|
||||||
|
- API Docs: https://platform.deepseek.com/api-docs
|
||||||
|
|
||||||
|
## ✨ مثالهای کاربردی
|
||||||
|
|
||||||
|
### تحلیل دادههای سنسور
|
||||||
|
```csharp
|
||||||
|
var data = $"دمای اتاق: {temp}°C، رطوبت: {humidity}%";
|
||||||
|
var suggestion = await _ai.AskSimpleAsync(
|
||||||
|
$"تحلیل کن: {data}",
|
||||||
|
"شما متخصص خانه هوشمند هستید"
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### چت با حافظه
|
||||||
|
```csharp
|
||||||
|
var messages = new List<ChatMessage>
|
||||||
|
{
|
||||||
|
new() { Role = "system", Content = "شما دستیار هوشمند هستید" },
|
||||||
|
new() { Role = "user", Content = "سلام" },
|
||||||
|
// ... تاریخچه قبلی
|
||||||
|
new() { Role = "user", Content = "پیام جدید" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _ai.AskAsync(new ChatRequest
|
||||||
|
{
|
||||||
|
Messages = messages
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎉 آماده استفاده!
|
||||||
|
|
||||||
|
پروژه کامل شده و آماده استفاده است. فقط API Key خود را در appsettings.json قرار دهید و از AI استفاده کنید! 🚀
|
||||||
|
|
||||||
110
src/GreenHome.AI.DeepSeek/ServiceCollectionExtensions.cs
Normal file
110
src/GreenHome.AI.DeepSeek/ServiceCollectionExtensions.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for registering DeepSeek AI service
|
||||||
|
/// </summary>
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds DeepSeek AI service to the service collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The service collection</param>
|
||||||
|
/// <param name="configuration">Configuration root</param>
|
||||||
|
/// <returns>The service collection for chaining</returns>
|
||||||
|
public static IServiceCollection AddDeepSeek(
|
||||||
|
this IServiceCollection services,
|
||||||
|
IConfiguration configuration)
|
||||||
|
{
|
||||||
|
return services.AddDeepSeek(configuration.GetSection("DeepSeek"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds DeepSeek AI service to the service collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The service collection</param>
|
||||||
|
/// <param name="configurationSection">Configuration section for DeepSeek</param>
|
||||||
|
/// <returns>The service collection for chaining</returns>
|
||||||
|
public static IServiceCollection AddDeepSeek(
|
||||||
|
this IServiceCollection services,
|
||||||
|
IConfigurationSection? configurationSection = null)
|
||||||
|
{
|
||||||
|
// Configure options
|
||||||
|
DeepSeekOptions? options = null;
|
||||||
|
if (configurationSection != null)
|
||||||
|
{
|
||||||
|
options = configurationSection.Get<DeepSeekOptions>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"DeepSeek configuration section is missing. " +
|
||||||
|
"Please add 'DeepSeek' section to your appsettings.json with 'ApiKey' property.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(options.ApiKey))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"DeepSeek ApiKey is required. " +
|
||||||
|
"Please add 'ApiKey' to the 'DeepSeek' section in your appsettings.json.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register options as singleton
|
||||||
|
services.AddSingleton(options);
|
||||||
|
|
||||||
|
// Register HttpClient and service
|
||||||
|
services.AddHttpClient<IDeepSeekService, DeepSeekService>(client =>
|
||||||
|
{
|
||||||
|
// Ensure BaseUrl ends with / for proper relative path handling
|
||||||
|
var baseUrl = options.BaseUrl.TrimEnd('/') + "/";
|
||||||
|
client.BaseAddress = new Uri(baseUrl);
|
||||||
|
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {options.ApiKey}");
|
||||||
|
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
|
||||||
|
client.Timeout = TimeSpan.FromSeconds(60); // AI requests may take longer
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds DeepSeek AI service to the service collection with explicit options
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The service collection</param>
|
||||||
|
/// <param name="configureOptions">Action to configure options</param>
|
||||||
|
/// <returns>The service collection for chaining</returns>
|
||||||
|
public static IServiceCollection AddDeepSeek(
|
||||||
|
this IServiceCollection services,
|
||||||
|
Action<DeepSeekOptions> configureOptions)
|
||||||
|
{
|
||||||
|
var options = new DeepSeekOptions
|
||||||
|
{
|
||||||
|
ApiKey = string.Empty // Will be set by configureOptions
|
||||||
|
};
|
||||||
|
configureOptions(options);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(options.ApiKey))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"DeepSeek ApiKey is required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register options as singleton
|
||||||
|
services.AddSingleton(options);
|
||||||
|
|
||||||
|
// Register HttpClient and service
|
||||||
|
services.AddHttpClient<IDeepSeekService, DeepSeekService>(client =>
|
||||||
|
{
|
||||||
|
var baseUrl = options.BaseUrl.TrimEnd('/') + "/";
|
||||||
|
client.BaseAddress = new Uri(baseUrl);
|
||||||
|
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bearer {options.ApiKey}");
|
||||||
|
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
|
||||||
|
client.Timeout = TimeSpan.FromSeconds(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
186
src/GreenHome.AI.DeepSeek/USAGE_FA.md
Normal file
186
src/GreenHome.AI.DeepSeek/USAGE_FA.md
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
# راهنمای سریع استفاده از سرویس DeepSeek
|
||||||
|
|
||||||
|
## نصب و راهاندازی
|
||||||
|
|
||||||
|
### گام 1: دریافت API Key
|
||||||
|
|
||||||
|
1. به آدرس https://platform.deepseek.com بروید
|
||||||
|
2. ثبتنام کنید یا وارد شوید
|
||||||
|
3. از منوی API Keys یک کلید جدید بسازید
|
||||||
|
4. کلید را کپی کنید (مهم: فقط یک بار نمایش داده میشود!)
|
||||||
|
|
||||||
|
### گام 2: تنظیم API Key
|
||||||
|
|
||||||
|
API Key خود را در فایل `appsettings.json` قرار دهید:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DeepSeek": {
|
||||||
|
"ApiKey": "کلید-API-خود-را-اینجا-قرار-دهید"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**هشدار امنیتی:** هرگز API Key را در Git commit نکنید!
|
||||||
|
|
||||||
|
### گام 3: اجرای برنامه
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd GreenHome.Api
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
## استفاده از API
|
||||||
|
|
||||||
|
سرویس روی آدرس `http://localhost:5000` (یا پورت دیگری که تنظیم کردهاید) اجرا میشود.
|
||||||
|
|
||||||
|
### 1. پرسیدن یک سوال ساده
|
||||||
|
|
||||||
|
**درخواست:**
|
||||||
|
```http
|
||||||
|
POST /api/ai/ask
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"question": "چگونه میتوانم مصرف انرژی خانه را کاهش دهم؟"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**پاسخ:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"question": "چگونه میتوانم مصرف انرژی خانه را کاهش دهم؟",
|
||||||
|
"answer": "برای کاهش مصرف انرژی خانه میتوانید از راهکارهای زیر استفاده کنید:\n1. از لامپهای LED استفاده کنید\n2. ترموستات هوشمند نصب کنید\n3. عایقبندی خانه را بهبود دهید...",
|
||||||
|
"timestamp": "2025-12-16T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. دریافت پیشنهادات برای خانه هوشمند
|
||||||
|
|
||||||
|
**درخواست:**
|
||||||
|
```http
|
||||||
|
POST /api/ai/suggest
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"deviceContext": "دمای فعلی: 28 درجه، رطوبت: 65%، ساعت: 14:00، تعداد افراد در خانه: 2 نفر"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**پاسخ:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"suggestions": "با توجه به شرایط فعلی، پیشنهادات زیر را دارم:\n- دمای 28 درجه کمی بالا است، روشن کردن کولر با دمای 24-25 درجه توصیه میشود\n- رطوبت 65% در محدوده مناسب است\n- در این ساعت از روز (14:00) پردهها را بکشید تا آفتاب مستقیم وارد نشود",
|
||||||
|
"timestamp": "2025-12-16T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. چت پیشرفته
|
||||||
|
|
||||||
|
**درخواست:**
|
||||||
|
```http
|
||||||
|
POST /api/ai/chat
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "شما یک دستیار هوشمند خانه هوشمند هستید."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "دمای خانه 18 درجه است"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "درجه حرارت 18 درجه را دریافت کردم. این دما کمی پایین است."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "چه کار کنم؟"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature": 0.7
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## مثالهای Curl
|
||||||
|
|
||||||
|
### سوال ساده
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5000/api/ai/ask \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"question":"بهترین دمای کولر برای خواب چیست؟"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### دریافت پیشنهاد
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:5000/api/ai/suggest \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"deviceContext":"دمای اتاق خواب: 26 درجه، ساعت: 22:00"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## استفاده در کد C#
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using GreenHome.AI.DeepSeek;
|
||||||
|
|
||||||
|
public class MyService
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService _ai;
|
||||||
|
|
||||||
|
public MyService(IDeepSeekService ai)
|
||||||
|
{
|
||||||
|
_ai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetAdvice()
|
||||||
|
{
|
||||||
|
var answer = await _ai.AskSimpleAsync(
|
||||||
|
"چگونه خانه هوشمند خود را امنتر کنم؟"
|
||||||
|
);
|
||||||
|
|
||||||
|
return answer ?? "پاسخی دریافت نشد";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## نکات مهم
|
||||||
|
|
||||||
|
### هزینه
|
||||||
|
- هر درخواست به API DeepSeek هزینه دارد
|
||||||
|
- بر اساس تعداد توکنهای استفاده شده محاسبه میشود
|
||||||
|
- برای کاهش هزینه، سوالات را مختصر و مفید بپرسید
|
||||||
|
|
||||||
|
### محدودیتها
|
||||||
|
- تعداد درخواست در دقیقه محدود است
|
||||||
|
- اگر خطای 429 دریافت کردید، کمی صبر کنید
|
||||||
|
|
||||||
|
### بهینهسازی
|
||||||
|
- از `temperature` پایینتر (0.3-0.7) برای پاسخهای دقیقتر استفاده کنید
|
||||||
|
- `maxTokens` را برای کنترل طول پاسخ تنظیم کنید
|
||||||
|
- پاسخهای تکراری را cache کنید
|
||||||
|
|
||||||
|
## عیبیابی
|
||||||
|
|
||||||
|
### خطا: 401 Unauthorized
|
||||||
|
- API Key را چک کنید
|
||||||
|
- مطمئن شوید که در appsettings.json صحیح است
|
||||||
|
|
||||||
|
### خطا: 429 Too Many Requests
|
||||||
|
- به محدودیت تعداد درخواست رسیدهاید
|
||||||
|
- 1-2 دقیقه صبر کنید
|
||||||
|
|
||||||
|
### خطا: Timeout
|
||||||
|
- درخواست طولانی است
|
||||||
|
- `maxTokens` را کاهش دهید
|
||||||
|
- timeout را افزایش دهید
|
||||||
|
|
||||||
|
## پشتیبانی
|
||||||
|
|
||||||
|
برای سوالات و مشکلات:
|
||||||
|
- مستندات کامل: [README.md](README.md)
|
||||||
|
- وبسایت DeepSeek: https://platform.deepseek.com
|
||||||
|
- مستندات API: https://platform.deepseek.com/api-docs
|
||||||
|
|
||||||
358
src/GreenHome.Api/Controllers/AIController.cs
Normal file
358
src/GreenHome.Api/Controllers/AIController.cs
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
using GreenHome.AI.DeepSeek;
|
||||||
|
using GreenHome.Application;
|
||||||
|
using GreenHome.Domain;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class AIController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDeepSeekService deepSeekService;
|
||||||
|
private readonly IAIQueryService aiQueryService;
|
||||||
|
private readonly ILogger<AIController> logger;
|
||||||
|
|
||||||
|
public AIController(
|
||||||
|
IDeepSeekService deepSeekService,
|
||||||
|
IAIQueryService aiQueryService,
|
||||||
|
ILogger<AIController> logger)
|
||||||
|
{
|
||||||
|
this.deepSeekService = deepSeekService;
|
||||||
|
this.aiQueryService = aiQueryService;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a simple question to the AI and get a response
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Question request</param>
|
||||||
|
/// <returns>AI response</returns>
|
||||||
|
[HttpPost("ask")]
|
||||||
|
public async Task<IActionResult> AskQuestion([FromBody] SimpleQuestionRequest request)
|
||||||
|
{
|
||||||
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Question))
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "Question is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("Processing AI question: {Question}", request.Question);
|
||||||
|
|
||||||
|
// Build chat request to get token information
|
||||||
|
var messages = new List<ChatMessage>();
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.SystemPrompt))
|
||||||
|
{
|
||||||
|
messages.Add(new ChatMessage { Role = "system", Content = request.SystemPrompt });
|
||||||
|
}
|
||||||
|
messages.Add(new ChatMessage { Role = "user", Content = request.Question });
|
||||||
|
|
||||||
|
var chatRequest = new ChatRequest { Messages = messages };
|
||||||
|
var chatResponse = await deepSeekService.AskAsync(chatRequest);
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
if (chatResponse == null || chatResponse.Choices == null || !chatResponse.Choices.Any())
|
||||||
|
{
|
||||||
|
return StatusCode(500, new { error = "No response received from AI" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var answer = chatResponse.Choices.FirstOrDefault()?.Message?.Content ?? "";
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
var aiQuery = new AIQuery
|
||||||
|
{
|
||||||
|
Question = request.Question,
|
||||||
|
Answer = answer,
|
||||||
|
DeviceId = request.DeviceId,
|
||||||
|
UserId = request.UserId,
|
||||||
|
Model = chatResponse.Model,
|
||||||
|
PromptTokens = chatResponse.Usage?.PromptTokens ?? 0,
|
||||||
|
CompletionTokens = chatResponse.Usage?.CompletionTokens ?? 0,
|
||||||
|
TotalTokens = chatResponse.Usage?.TotalTokens ?? 0,
|
||||||
|
ResponseTimeMs = stopwatch.ElapsedMilliseconds
|
||||||
|
};
|
||||||
|
|
||||||
|
await aiQueryService.SaveQueryAsync(aiQuery);
|
||||||
|
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
question = request.Question,
|
||||||
|
answer = answer,
|
||||||
|
deviceId = request.DeviceId,
|
||||||
|
tokens = new
|
||||||
|
{
|
||||||
|
prompt = aiQuery.PromptTokens,
|
||||||
|
completion = aiQuery.CompletionTokens,
|
||||||
|
total = aiQuery.TotalTokens
|
||||||
|
},
|
||||||
|
responseTimeMs = aiQuery.ResponseTimeMs,
|
||||||
|
timestamp = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error processing AI question");
|
||||||
|
return StatusCode(500, new { error = "An error occurred while processing your question" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a complex chat request with multiple messages to the AI
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Extended chat request with deviceId</param>
|
||||||
|
/// <returns>AI chat response</returns>
|
||||||
|
[HttpPost("chat")]
|
||||||
|
public async Task<IActionResult> Chat([FromBody] ExtendedChatRequest request)
|
||||||
|
{
|
||||||
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (request.Messages == null || !request.Messages.Any())
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "At least one message is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("Processing AI chat with {MessageCount} messages", request.Messages.Count);
|
||||||
|
|
||||||
|
var chatRequest = new ChatRequest
|
||||||
|
{
|
||||||
|
Messages = request.Messages,
|
||||||
|
Model = request.Model,
|
||||||
|
Temperature = request.Temperature,
|
||||||
|
MaxTokens = request.MaxTokens
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await deepSeekService.AskAsync(chatRequest);
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
if (response == null || response.Choices == null || !response.Choices.Any())
|
||||||
|
{
|
||||||
|
return StatusCode(500, new { error = "No response received from AI" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract question and answer
|
||||||
|
var userMessage = request.Messages.LastOrDefault(m => m.Role == "user");
|
||||||
|
var question = userMessage?.Content ?? "Complex chat";
|
||||||
|
var answer = response.Choices.FirstOrDefault()?.Message?.Content ?? "";
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
var aiQuery = new AIQuery
|
||||||
|
{
|
||||||
|
Question = question,
|
||||||
|
Answer = answer,
|
||||||
|
DeviceId = request.DeviceId,
|
||||||
|
UserId = request.UserId,
|
||||||
|
Model = response.Model,
|
||||||
|
Temperature = request.Temperature,
|
||||||
|
PromptTokens = response.Usage?.PromptTokens ?? 0,
|
||||||
|
CompletionTokens = response.Usage?.CompletionTokens ?? 0,
|
||||||
|
TotalTokens = response.Usage?.TotalTokens ?? 0,
|
||||||
|
ResponseTimeMs = stopwatch.ElapsedMilliseconds
|
||||||
|
};
|
||||||
|
|
||||||
|
await aiQueryService.SaveQueryAsync(aiQuery);
|
||||||
|
|
||||||
|
return Ok(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error processing AI chat");
|
||||||
|
return StatusCode(500, new { error = "An error occurred while processing your chat request" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get suggestions for smart home automation based on device data
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Device context request</param>
|
||||||
|
/// <returns>AI suggestions</returns>
|
||||||
|
[HttpPost("suggest")]
|
||||||
|
public async Task<IActionResult> GetSuggestions([FromBody] SuggestionRequest request)
|
||||||
|
{
|
||||||
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var systemPrompt = @"شما یک مشاور هوشمند خانه هوشمند هستید. بر اساس دادههای دستگاههای IoT، پیشنهادهای عملی و مفید برای بهینهسازی مصرف انرژی، راحتی و امنیت ارائه دهید. پاسخ را به زبان فارسی و به صورت خلاصه و کاربردی بنویسید.";
|
||||||
|
|
||||||
|
var question = $@"وضعیت فعلی دستگاههای خانه هوشمند:
|
||||||
|
{request.DeviceContext}
|
||||||
|
|
||||||
|
لطفاً پیشنهادات خود را برای بهبود وضعیت ارائه دهید.";
|
||||||
|
|
||||||
|
var messages = new List<ChatMessage>
|
||||||
|
{
|
||||||
|
new ChatMessage { Role = "system", Content = systemPrompt },
|
||||||
|
new ChatMessage { Role = "user", Content = question }
|
||||||
|
};
|
||||||
|
|
||||||
|
var chatRequest = new ChatRequest { Messages = messages };
|
||||||
|
var chatResponse = await deepSeekService.AskAsync(chatRequest);
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
if (chatResponse == null || chatResponse.Choices == null || !chatResponse.Choices.Any())
|
||||||
|
{
|
||||||
|
return StatusCode(500, new { error = "No suggestions received from AI" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var answer = chatResponse.Choices.FirstOrDefault()?.Message?.Content ?? "";
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
var aiQuery = new AIQuery
|
||||||
|
{
|
||||||
|
Question = question,
|
||||||
|
Answer = answer,
|
||||||
|
DeviceId = request.DeviceId,
|
||||||
|
UserId = request.UserId,
|
||||||
|
Model = chatResponse.Model,
|
||||||
|
PromptTokens = chatResponse.Usage?.PromptTokens ?? 0,
|
||||||
|
CompletionTokens = chatResponse.Usage?.CompletionTokens ?? 0,
|
||||||
|
TotalTokens = chatResponse.Usage?.TotalTokens ?? 0,
|
||||||
|
ResponseTimeMs = stopwatch.ElapsedMilliseconds
|
||||||
|
};
|
||||||
|
|
||||||
|
await aiQueryService.SaveQueryAsync(aiQuery);
|
||||||
|
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
suggestions = answer,
|
||||||
|
deviceId = request.DeviceId,
|
||||||
|
tokens = new
|
||||||
|
{
|
||||||
|
prompt = aiQuery.PromptTokens,
|
||||||
|
completion = aiQuery.CompletionTokens,
|
||||||
|
total = aiQuery.TotalTokens
|
||||||
|
},
|
||||||
|
responseTimeMs = aiQuery.ResponseTimeMs,
|
||||||
|
timestamp = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error getting AI suggestions");
|
||||||
|
return StatusCode(500, new { error = "An error occurred while getting suggestions" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get AI query history for a device
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("history/device/{deviceId}")]
|
||||||
|
public async Task<IActionResult> GetDeviceHistory(int deviceId, [FromQuery] int take = 50)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var queries = await aiQueryService.GetDeviceQueriesAsync(deviceId, take);
|
||||||
|
var totalTokens = await aiQueryService.GetDeviceTotalTokensAsync(deviceId);
|
||||||
|
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
queries = queries.Select(q => new
|
||||||
|
{
|
||||||
|
q.Id,
|
||||||
|
q.Question,
|
||||||
|
q.Answer,
|
||||||
|
q.TotalTokens,
|
||||||
|
q.PromptTokens,
|
||||||
|
q.CompletionTokens,
|
||||||
|
q.Model,
|
||||||
|
q.ResponseTimeMs,
|
||||||
|
q.CreatedAt
|
||||||
|
}),
|
||||||
|
totalTokens
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error getting device history");
|
||||||
|
return StatusCode(500, new { error = "An error occurred" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get AI query statistics
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("stats")]
|
||||||
|
public async Task<IActionResult> GetStats()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stats = await aiQueryService.GetStatsAsync();
|
||||||
|
return Ok(stats);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Error getting stats");
|
||||||
|
return StatusCode(500, new { error = "An error occurred" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simple question request model
|
||||||
|
/// </summary>
|
||||||
|
public class SimpleQuestionRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The question to ask the AI
|
||||||
|
/// </summary>
|
||||||
|
public required string Question { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional system prompt to set context for the AI
|
||||||
|
/// </summary>
|
||||||
|
public string? SystemPrompt { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional device ID to associate with this query
|
||||||
|
/// </summary>
|
||||||
|
public int? DeviceId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional user ID to associate with this query
|
||||||
|
/// </summary>
|
||||||
|
public int? UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended chat request with device tracking
|
||||||
|
/// </summary>
|
||||||
|
public class ExtendedChatRequest
|
||||||
|
{
|
||||||
|
public required List<ChatMessage> Messages { get; set; }
|
||||||
|
public string Model { get; set; } = "deepseek-chat";
|
||||||
|
public double? Temperature { get; set; }
|
||||||
|
public int? MaxTokens { get; set; }
|
||||||
|
public int? DeviceId { get; set; }
|
||||||
|
public int? UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Suggestion request for smart home automation
|
||||||
|
/// </summary>
|
||||||
|
public class SuggestionRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Context about devices and their current state
|
||||||
|
/// </summary>
|
||||||
|
public required string DeviceContext { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Device ID for this suggestion request
|
||||||
|
/// </summary>
|
||||||
|
public int? DeviceId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User ID for this suggestion request
|
||||||
|
/// </summary>
|
||||||
|
public int? UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
85
src/GreenHome.Api/Controllers/AlertConditionsController.cs
Normal file
85
src/GreenHome.Api/Controllers/AlertConditionsController.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class AlertConditionsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IAlertConditionService alertConditionService;
|
||||||
|
|
||||||
|
public AlertConditionsController(IAlertConditionService alertConditionService)
|
||||||
|
{
|
||||||
|
this.alertConditionService = alertConditionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت تمام شرایط هشدار یک دستگاه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("device/{deviceId}")]
|
||||||
|
public async Task<ActionResult<IReadOnlyList<AlertConditionDto>>> GetByDeviceId(int deviceId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await alertConditionService.GetByDeviceIdAsync(deviceId, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت یک شرط هشدار با ID
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<ActionResult<AlertConditionDto>> GetById(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await alertConditionService.GetByIdAsync(id, cancellationToken);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد شرط هشدار جدید
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<int>> Create(CreateAlertConditionRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var id = await alertConditionService.CreateAsync(request, cancellationToken);
|
||||||
|
return Ok(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// بهروزرسانی شرط هشدار
|
||||||
|
/// </summary>
|
||||||
|
[HttpPut]
|
||||||
|
public async Task<ActionResult> Update(UpdateAlertConditionRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await alertConditionService.UpdateAsync(request, cancellationToken);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حذف شرط هشدار
|
||||||
|
/// </summary>
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<ActionResult> Delete(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await alertConditionService.DeleteAsync(id, cancellationToken);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فعال/غیرفعال کردن شرط هشدار
|
||||||
|
/// </summary>
|
||||||
|
[HttpPatch("{id}/toggle")]
|
||||||
|
public async Task<ActionResult> ToggleEnabled(int id, [FromBody] bool isEnabled, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await alertConditionService.ToggleEnabledAsync(id, isEnabled, cancellationToken);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
62
src/GreenHome.Api/Controllers/AlertLogsController.cs
Normal file
62
src/GreenHome.Api/Controllers/AlertLogsController.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class AlertLogsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IAlertLogService _alertLogService;
|
||||||
|
|
||||||
|
public AlertLogsController(IAlertLogService alertLogService)
|
||||||
|
{
|
||||||
|
_alertLogService = alertLogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت لیست لاگهای هشدار با فیلتر و صفحهبندی
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PagedResult<AlertLogDto>>> GetAlertLogs(
|
||||||
|
[FromQuery] int? deviceId,
|
||||||
|
[FromQuery] int? userId,
|
||||||
|
[FromQuery] Domain.AlertType? alertType,
|
||||||
|
[FromQuery] Domain.AlertStatus? status,
|
||||||
|
[FromQuery] DateTime? startDate,
|
||||||
|
[FromQuery] DateTime? endDate,
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 20,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var filter = new AlertLogFilter
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
UserId = userId,
|
||||||
|
AlertType = alertType,
|
||||||
|
Status = status,
|
||||||
|
StartDate = startDate,
|
||||||
|
EndDate = endDate,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _alertLogService.GetAlertLogsAsync(filter, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت جزئیات کامل یک لاگ هشدار
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<ActionResult<AlertLogDto>> GetAlertLogById(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _alertLogService.GetAlertLogByIdAsync(id, cancellationToken);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = $"لاگ هشدار با شناسه {id} یافت نشد" });
|
||||||
|
}
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
98
src/GreenHome.Api/Controllers/ChecklistsController.cs
Normal file
98
src/GreenHome.Api/Controllers/ChecklistsController.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class ChecklistsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IChecklistService _checklistService;
|
||||||
|
|
||||||
|
public ChecklistsController(IChecklistService checklistService)
|
||||||
|
{
|
||||||
|
_checklistService = checklistService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت چکلیست فعال یک دستگاه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("active/{deviceId}")]
|
||||||
|
public async Task<ActionResult<ChecklistDto>> GetActiveChecklist(int deviceId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _checklistService.GetActiveChecklistByDeviceIdAsync(deviceId, cancellationToken);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = "چکلیست فعالی برای این دستگاه یافت نشد" });
|
||||||
|
}
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت تمام چکلیستهای یک دستگاه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("device/{deviceId}")]
|
||||||
|
public async Task<ActionResult<List<ChecklistDto>>> GetChecklists(int deviceId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _checklistService.GetChecklistsByDeviceIdAsync(deviceId, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت جزئیات یک چکلیست
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<ActionResult<ChecklistDto>> GetChecklistById(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _checklistService.GetChecklistByIdAsync(id, cancellationToken);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = $"چکلیست با شناسه {id} یافت نشد" });
|
||||||
|
}
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد چکلیست جدید (چکلیست قبلی غیرفعال میشود)
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<int>> CreateChecklist(
|
||||||
|
CreateChecklistRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var id = await _checklistService.CreateChecklistAsync(request, cancellationToken);
|
||||||
|
return Ok(new { id, message = "چکلیست با موفقیت ایجاد شد و چکلیست قبلی غیرفعال شد" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت سابقه تکمیلهای یک چکلیست
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{checklistId}/completions")]
|
||||||
|
public async Task<ActionResult<List<ChecklistCompletionDto>>> GetCompletions(
|
||||||
|
int checklistId,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _checklistService.GetCompletionsByChecklistIdAsync(checklistId, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ثبت تکمیل چکلیست
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("complete")]
|
||||||
|
public async Task<ActionResult<int>> CompleteChecklist(
|
||||||
|
CompleteChecklistRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var id = await _checklistService.CompleteChecklistAsync(request, cancellationToken);
|
||||||
|
return Ok(new { id, message = "چکلیست با موفقیت تکمیل شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
143
src/GreenHome.Api/Controllers/DailyReportController.cs
Normal file
143
src/GreenHome.Api/Controllers/DailyReportController.cs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class DailyReportController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDailyReportService _dailyReportService;
|
||||||
|
private readonly ILogger<DailyReportController> _logger;
|
||||||
|
|
||||||
|
public DailyReportController(
|
||||||
|
IDailyReportService dailyReportService,
|
||||||
|
ILogger<DailyReportController> logger)
|
||||||
|
{
|
||||||
|
_dailyReportService = dailyReportService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت یا ایجاد گزارش تحلیل روزانه گلخانه
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">شناسه دستگاه</param>
|
||||||
|
/// <param name="persianDate">تاریخ شمسی به فرمت yyyy/MM/dd</param>
|
||||||
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
|
/// <returns>گزارش تحلیل روزانه</returns>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<DailyReportResponse>> GetDailyReport(
|
||||||
|
[FromQuery] int deviceId,
|
||||||
|
[FromQuery] string persianDate,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (deviceId <= 0)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "شناسه دستگاه نامعتبر است" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(persianDate))
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "تاریخ نباید خالی باشد" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = new DailyReportRequest
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
PersianDate = persianDate.Trim()
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _dailyReportService.GetOrCreateDailyReportAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"گزارش روزانه برای دستگاه {DeviceId} و تاریخ {Date} با موفقیت برگشت داده شد (FromCache: {FromCache})",
|
||||||
|
deviceId, persianDate, result.FromCache);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "درخواست نامعتبر برای دستگاه {DeviceId} و تاریخ {Date}", deviceId, persianDate);
|
||||||
|
return BadRequest(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "خطا در پردازش گزارش روزانه برای دستگاه {DeviceId} و تاریخ {Date}", deviceId, persianDate);
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "خطای سرور در دریافت گزارش روزانه برای دستگاه {DeviceId} و تاریخ {Date}", deviceId, persianDate);
|
||||||
|
return StatusCode(500, new { error = "خطای سرور در پردازش درخواست" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت تحلیل هفتگی
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("weekly")]
|
||||||
|
public async Task<ActionResult<DailyReportResponse>> GetWeeklyAnalysis(
|
||||||
|
[FromQuery] int deviceId,
|
||||||
|
[FromQuery] string startDate,
|
||||||
|
[FromQuery] string endDate,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new WeeklyAnalysisRequest
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
StartDate = startDate.Trim(),
|
||||||
|
EndDate = endDate.Trim()
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _dailyReportService.GetWeeklyAnalysisAsync(request, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error getting weekly analysis");
|
||||||
|
return StatusCode(500, new { error = "خطا در دریافت تحلیل هفتگی" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت تحلیل ماهانه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("monthly")]
|
||||||
|
public async Task<ActionResult<DailyReportResponse>> GetMonthlyAnalysis(
|
||||||
|
[FromQuery] int deviceId,
|
||||||
|
[FromQuery] int year,
|
||||||
|
[FromQuery] int month,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new MonthlyAnalysisRequest
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
Year = year,
|
||||||
|
Month = month
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _dailyReportService.GetMonthlyAnalysisAsync(request, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error getting monthly analysis");
|
||||||
|
return StatusCode(500, new { error = "خطا در دریافت تحلیل ماهانه" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
212
src/GreenHome.Api/Controllers/DevicePostsController.cs
Normal file
212
src/GreenHome.Api/Controllers/DevicePostsController.cs
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class DevicePostsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDevicePostService _postService;
|
||||||
|
private readonly ILogger<DevicePostsController> _logger;
|
||||||
|
private readonly IWebHostEnvironment _environment;
|
||||||
|
|
||||||
|
public DevicePostsController(
|
||||||
|
IDevicePostService postService,
|
||||||
|
ILogger<DevicePostsController> logger,
|
||||||
|
IWebHostEnvironment environment)
|
||||||
|
{
|
||||||
|
_postService = postService;
|
||||||
|
_logger = logger;
|
||||||
|
_environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت پستهای گروه مجازی دستگاه (تایملاین)
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PagedResult<DevicePostDto>>> GetPosts(
|
||||||
|
[FromQuery] int deviceId,
|
||||||
|
[FromQuery] int? authorUserId,
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 20,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var filter = new DevicePostFilter
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
AuthorUserId = authorUserId,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _postService.GetPostsAsync(filter, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت جزئیات یک پست
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<ActionResult<DevicePostDto>> GetPostById(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _postService.GetPostByIdAsync(id, cancellationToken);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = $"پست با شناسه {id} یافت نشد" });
|
||||||
|
}
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد پست جدید در گروه مجازی
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<int>> CreatePost(
|
||||||
|
CreateDevicePostRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var id = await _postService.CreatePostAsync(request, cancellationToken);
|
||||||
|
return Ok(new { id, message = "پست با موفقیت ایجاد شد" });
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
|
{
|
||||||
|
return Unauthorized(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ویرایش پست
|
||||||
|
/// </summary>
|
||||||
|
[HttpPut]
|
||||||
|
public async Task<ActionResult> UpdatePost(
|
||||||
|
UpdateDevicePostRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _postService.UpdatePostAsync(request, cancellationToken);
|
||||||
|
return Ok(new { message = "پست با موفقیت ویرایش شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حذف پست
|
||||||
|
/// </summary>
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<ActionResult> DeletePost(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _postService.DeletePostAsync(id, cancellationToken);
|
||||||
|
return Ok(new { message = "پست با موفقیت حذف شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آپلود تصویر برای پست
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("{postId}/images")]
|
||||||
|
[Consumes("multipart/form-data")]
|
||||||
|
public async Task<ActionResult<int>> UploadImage(
|
||||||
|
int postId,
|
||||||
|
[FromForm] IFormFile file,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (file == null || file.Length == 0)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "فایل انتخاب نشده است" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file type
|
||||||
|
var allowedTypes = new[] { "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp" };
|
||||||
|
if (!allowedTypes.Contains(file.ContentType.ToLower()))
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "فقط فایلهای تصویری مجاز هستند" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file size (max 5MB)
|
||||||
|
if (file.Length > 5 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "حجم فایل نباید بیشتر از 5 مگابایت باشد" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create upload directory
|
||||||
|
var uploadsFolder = Path.Combine(_environment.WebRootPath ?? "wwwroot", "uploads", "posts");
|
||||||
|
Directory.CreateDirectory(uploadsFolder);
|
||||||
|
|
||||||
|
// Generate unique filename
|
||||||
|
var fileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}";
|
||||||
|
var filePath = Path.Combine(uploadsFolder, fileName);
|
||||||
|
|
||||||
|
// Save file
|
||||||
|
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(stream, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
var relativePath = $"/uploads/posts/{fileName}";
|
||||||
|
var imageId = await _postService.AddImageToPostAsync(
|
||||||
|
postId,
|
||||||
|
file.FileName,
|
||||||
|
relativePath,
|
||||||
|
file.ContentType,
|
||||||
|
file.Length,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation("Image uploaded for post {PostId}: {ImageId}", postId, imageId);
|
||||||
|
|
||||||
|
return Ok(new { imageId, filePath = relativePath, message = "تصویر با موفقیت آپلود شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error uploading image for post {PostId}", postId);
|
||||||
|
return StatusCode(500, new { error = "خطا در آپلود تصویر" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حذف تصویر از پست
|
||||||
|
/// </summary>
|
||||||
|
[HttpDelete("images/{imageId}")]
|
||||||
|
public async Task<ActionResult> DeleteImage(int imageId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _postService.DeleteImageAsync(imageId, cancellationToken);
|
||||||
|
return Ok(new { message = "تصویر با موفقیت حذف شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// بررسی دسترسی کاربر به دستگاه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("access/{userId}/{deviceId}")]
|
||||||
|
public async Task<ActionResult<bool>> CheckAccess(int userId, int deviceId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var hasAccess = await _postService.CanUserAccessDeviceAsync(userId, deviceId, cancellationToken);
|
||||||
|
return Ok(new { hasAccess });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
128
src/GreenHome.Api/Controllers/DeviceTokenController.cs
Normal file
128
src/GreenHome.Api/Controllers/DeviceTokenController.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
using GreenHome.Application;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// کنترلر مدیریت توکن و تنظیمات دستگاه
|
||||||
|
/// </summary>
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class DeviceTokenController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IDeviceTokenService deviceTokenService;
|
||||||
|
private readonly ILogger<DeviceTokenController> logger;
|
||||||
|
|
||||||
|
public DeviceTokenController(
|
||||||
|
IDeviceTokenService deviceTokenService,
|
||||||
|
ILogger<DeviceTokenController> logger)
|
||||||
|
{
|
||||||
|
this.deviceTokenService = deviceTokenService;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت فاصله زمانی آپلود دستگاه
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">شناسه دستگاه (اختیاری)</param>
|
||||||
|
/// <param name="devicePhoneNumber">شماره تلفن دستگاه (اختیاری)</param>
|
||||||
|
/// <returns>فاصله زمانی آپلود به دقیقه</returns>
|
||||||
|
[HttpGet("upload-interval")]
|
||||||
|
public async Task<ActionResult<GetUploadIntervalResponse>> GetUploadInterval(
|
||||||
|
[FromQuery] int? deviceId,
|
||||||
|
[FromQuery] string? devicePhoneNumber,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!deviceId.HasValue && string.IsNullOrWhiteSpace(devicePhoneNumber))
|
||||||
|
{
|
||||||
|
return BadRequest(new GetUploadIntervalResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Message = "حداقل یکی از پارامترهای deviceId یا devicePhoneNumber باید ارسال شود"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = new GetUploadIntervalRequest
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
DevicePhoneNumber = devicePhoneNumber
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await deviceTokenService.GetUploadIntervalAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
return NotFound(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// درخواست توکن دستگاه (تولید و ارسال کد از طریق پیامک)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">درخواست شامل شماره تلفن دستگاه</param>
|
||||||
|
/// <returns>نتیجه درخواست</returns>
|
||||||
|
[HttpPost("request-token")]
|
||||||
|
public async Task<ActionResult<RequestDeviceTokenResponse>> RequestToken(
|
||||||
|
[FromBody] RequestDeviceTokenRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.DevicePhoneNumber))
|
||||||
|
{
|
||||||
|
return BadRequest(new RequestDeviceTokenResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Message = "شماره تلفن دستگاه الزامی است"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await deviceTokenService.RequestDeviceTokenAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
return BadRequest(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// تایید توکن دستگاه (ارسال تنظیمات کدشده از طریق پیامک)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">درخواست شامل شماره تلفن و کد تایید</param>
|
||||||
|
/// <returns>نتیجه تایید و تنظیمات کدشده</returns>
|
||||||
|
[HttpPost("verify-token")]
|
||||||
|
public async Task<ActionResult<VerifyDeviceTokenResponse>> VerifyToken(
|
||||||
|
[FromBody] VerifyDeviceTokenRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.DevicePhoneNumber))
|
||||||
|
{
|
||||||
|
return BadRequest(new VerifyDeviceTokenResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Message = "شماره تلفن دستگاه الزامی است"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.VerificationCode))
|
||||||
|
{
|
||||||
|
return BadRequest(new VerifyDeviceTokenResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Message = "کد تایید الزامی است"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await deviceTokenService.VerifyDeviceTokenAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
return BadRequest(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
62
src/GreenHome.Api/Controllers/MonthlyReportController.cs
Normal file
62
src/GreenHome.Api/Controllers/MonthlyReportController.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class MonthlyReportController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IMonthlyReportService _monthlyReportService;
|
||||||
|
private readonly ILogger<MonthlyReportController> _logger;
|
||||||
|
|
||||||
|
public MonthlyReportController(
|
||||||
|
IMonthlyReportService monthlyReportService,
|
||||||
|
ILogger<MonthlyReportController> logger)
|
||||||
|
{
|
||||||
|
_monthlyReportService = monthlyReportService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت گزارش آماری ماهانه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<MonthlyReportDto>> GetMonthlyReport(
|
||||||
|
[FromQuery] int deviceId,
|
||||||
|
[FromQuery] int year,
|
||||||
|
[FromQuery] int month,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (deviceId <= 0)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "شناسه دستگاه نامعتبر است" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (month < 1 || month > 12)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "ماه باید بین 1 تا 12 باشد" });
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _monthlyReportService.GetMonthlyReportAsync(deviceId, year, month, cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"گزارش ماهانه برای دستگاه {DeviceId} و ماه {Month}/{Year} ایجاد شد",
|
||||||
|
deviceId, month, year);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error generating monthly report");
|
||||||
|
return StatusCode(500, new { error = "خطا در ایجاد گزارش ماهانه" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
60
src/GreenHome.Api/Controllers/PowerOutageController.cs
Normal file
60
src/GreenHome.Api/Controllers/PowerOutageController.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class PowerOutageController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IAlertService _alertService;
|
||||||
|
private readonly ILogger<PowerOutageController> _logger;
|
||||||
|
|
||||||
|
public PowerOutageController(
|
||||||
|
IAlertService alertService,
|
||||||
|
ILogger<PowerOutageController> logger)
|
||||||
|
{
|
||||||
|
_alertService = alertService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال هشدار قطع برق برای یک دستگاه
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">شناسه دستگاه</param>
|
||||||
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
|
/// <returns>نتیجه عملیات</returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult> SendPowerOutageAlert(
|
||||||
|
[FromQuery] int deviceId,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (deviceId <= 0)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "شناسه دستگاه نامعتبر است" });
|
||||||
|
}
|
||||||
|
|
||||||
|
await _alertService.SendPowerOutageAlertAsync(deviceId, cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation("Power outage alert processed for device {DeviceId}", deviceId);
|
||||||
|
|
||||||
|
return Ok(new {
|
||||||
|
success = true,
|
||||||
|
message = "هشدار قطع برق با موفقیت ارسال شد"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Invalid operation for power outage alert: DeviceId={DeviceId}", deviceId);
|
||||||
|
return BadRequest(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error sending power outage alert: DeviceId={DeviceId}", deviceId);
|
||||||
|
return StatusCode(500, new { error = "خطا در ارسال هشدار قطع برق" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -25,12 +25,14 @@ public class TelemetryController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("AddData")]
|
[HttpGet("AddData")]
|
||||||
public async Task<ActionResult<int>> Create(string deviceName, decimal temperatureC, decimal humidityPercent,
|
public async Task<ActionResult<int>> Create(int deviceId, decimal temperatureC, decimal humidityPercent,
|
||||||
decimal soilPercent, int gasPPM, decimal lux, CancellationToken cancellationToken)
|
decimal soilPercent, int gasPPM, decimal lux, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
|
||||||
TelemetryDto dto = new TelemetryDto
|
TelemetryDto dto = new TelemetryDto
|
||||||
{
|
{
|
||||||
DeviceName = deviceName,
|
//DeviceName = deviceName.ToString() == "dr110"? "dr110":"",
|
||||||
|
DeviceId = deviceId,
|
||||||
TemperatureC = temperatureC,
|
TemperatureC = temperatureC,
|
||||||
HumidityPercent = humidityPercent,
|
HumidityPercent = humidityPercent,
|
||||||
SoilPercent = soilPercent,
|
SoilPercent = soilPercent,
|
||||||
@@ -39,7 +41,7 @@ public class TelemetryController : ControllerBase
|
|||||||
TimestampUtc = DateTime.UtcNow
|
TimestampUtc = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
var id = await telemetryService.AddAsync(dto, cancellationToken);
|
var id = await telemetryService.AddAsync(dto, cancellationToken);
|
||||||
|
|
||||||
// Check and send alerts if needed (fire and forget)
|
// Check and send alerts if needed (fire and forget)
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@@ -58,7 +60,7 @@ public class TelemetryController : ControllerBase
|
|||||||
// Errors are logged in AlertService
|
// Errors are logged in AlertService
|
||||||
}
|
}
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
|
|
||||||
return Ok(id);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
210
src/GreenHome.Api/Controllers/UserDailyReportsController.cs
Normal file
210
src/GreenHome.Api/Controllers/UserDailyReportsController.cs
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using GreenHome.Application;
|
||||||
|
|
||||||
|
namespace GreenHome.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class UserDailyReportsController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IUserDailyReportService _reportService;
|
||||||
|
private readonly ILogger<UserDailyReportsController> _logger;
|
||||||
|
private readonly IWebHostEnvironment _environment;
|
||||||
|
|
||||||
|
public UserDailyReportsController(
|
||||||
|
IUserDailyReportService reportService,
|
||||||
|
ILogger<UserDailyReportsController> logger,
|
||||||
|
IWebHostEnvironment environment)
|
||||||
|
{
|
||||||
|
_reportService = reportService;
|
||||||
|
_logger = logger;
|
||||||
|
_environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت لیست گزارشهای روزانه کاربران با فیلتر
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PagedResult<UserDailyReportDto>>> GetReports(
|
||||||
|
[FromQuery] int? deviceId,
|
||||||
|
[FromQuery] int? userId,
|
||||||
|
[FromQuery] string? persianDate,
|
||||||
|
[FromQuery] int? year,
|
||||||
|
[FromQuery] int? month,
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 20,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var filter = new UserDailyReportFilter
|
||||||
|
{
|
||||||
|
DeviceId = deviceId,
|
||||||
|
UserId = userId,
|
||||||
|
PersianDate = persianDate,
|
||||||
|
Year = year,
|
||||||
|
Month = month,
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _reportService.GetReportsAsync(filter, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت جزئیات یک گزارش روزانه
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<ActionResult<UserDailyReportDto>> GetReportById(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _reportService.GetReportByIdAsync(id, cancellationToken);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = $"گزارش با شناسه {id} یافت نشد" });
|
||||||
|
}
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد گزارش روزانه جدید
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<int>> CreateReport(
|
||||||
|
CreateUserDailyReportRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var id = await _reportService.CreateReportAsync(request, cancellationToken);
|
||||||
|
return Ok(new { id, message = "گزارش با موفقیت ایجاد شد" });
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ویرایش گزارش روزانه
|
||||||
|
/// </summary>
|
||||||
|
[HttpPut]
|
||||||
|
public async Task<ActionResult> UpdateReport(
|
||||||
|
UpdateUserDailyReportRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _reportService.UpdateReportAsync(request, cancellationToken);
|
||||||
|
return Ok(new { message = "گزارش با موفقیت ویرایش شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حذف گزارش روزانه
|
||||||
|
/// </summary>
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<ActionResult> DeleteReport(int id, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _reportService.DeleteReportAsync(id, cancellationToken);
|
||||||
|
return Ok(new { message = "گزارش با موفقیت حذف شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آپلود تصویر برای گزارش روزانه
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("{reportId}/images")]
|
||||||
|
[Consumes("multipart/form-data")]
|
||||||
|
public async Task<ActionResult<int>> UploadImage(
|
||||||
|
int reportId,
|
||||||
|
[FromForm] IFormFile file,
|
||||||
|
[FromForm] string? description,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (file == null || file.Length == 0)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "فایل انتخاب نشده است" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file type
|
||||||
|
var allowedTypes = new[] { "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp" };
|
||||||
|
if (!allowedTypes.Contains(file.ContentType.ToLower()))
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "فقط فایلهای تصویری مجاز هستند" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file size (max 5MB)
|
||||||
|
if (file.Length > 5 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = "حجم فایل نباید بیشتر از 5 مگابایت باشد" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create upload directory
|
||||||
|
var uploadsFolder = Path.Combine(_environment.WebRootPath ?? "wwwroot", "uploads", "reports");
|
||||||
|
Directory.CreateDirectory(uploadsFolder);
|
||||||
|
|
||||||
|
// Generate unique filename
|
||||||
|
var fileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}";
|
||||||
|
var filePath = Path.Combine(uploadsFolder, fileName);
|
||||||
|
|
||||||
|
// Save file
|
||||||
|
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||||
|
{
|
||||||
|
await file.CopyToAsync(stream, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
var relativePath = $"/uploads/reports/{fileName}";
|
||||||
|
var imageId = await _reportService.AddImageToReportAsync(
|
||||||
|
reportId,
|
||||||
|
file.FileName,
|
||||||
|
relativePath,
|
||||||
|
file.ContentType,
|
||||||
|
file.Length,
|
||||||
|
description,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation("Image uploaded for report {ReportId}: {ImageId}", reportId, imageId);
|
||||||
|
|
||||||
|
return Ok(new { imageId, filePath = relativePath, message = "تصویر با موفقیت آپلود شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error uploading image for report {ReportId}", reportId);
|
||||||
|
return StatusCode(500, new { error = "خطا در آپلود تصویر" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حذف تصویر از گزارش
|
||||||
|
/// </summary>
|
||||||
|
[HttpDelete("images/{imageId}")]
|
||||||
|
public async Task<ActionResult> DeleteImage(int imageId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _reportService.DeleteImageAsync(imageId, cancellationToken);
|
||||||
|
return Ok(new { message = "تصویر با موفقیت حذف شد" });
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return NotFound(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -268,3 +268,6 @@ public class VoiceCallTestController : ControllerBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.9">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.9">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.9" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.9" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
<PackageReference Include="Scalar.AspNetCore" Version="2.11.6" />
|
||||||
</ItemGroup>
|
<Content Include="My_StaticFiles\**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<ItemGroup>
|
</Content>
|
||||||
<ProjectReference Include="..\GreenHome.Application\GreenHome.Application.csproj" />
|
</ItemGroup>
|
||||||
<ProjectReference Include="..\GreenHome.Infrastructure\GreenHome.Infrastructure.csproj" />
|
|
||||||
<ProjectReference Include="..\GreenHome.Sms.Ippanel\GreenHome.Sms.Ippanel.csproj" />
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\GreenHome.VoiceCall.Avanak\GreenHome.VoiceCall.Avanak.csproj" />
|
<ProjectReference Include="..\GreenHome.Application\GreenHome.Application.csproj" />
|
||||||
</ItemGroup>
|
<ProjectReference Include="..\GreenHome.Infrastructure\GreenHome.Infrastructure.csproj" />
|
||||||
|
<ProjectReference Include="..\GreenHome.Sms.Ippanel\GreenHome.Sms.Ippanel.csproj" />
|
||||||
</Project>
|
<ProjectReference Include="..\GreenHome.VoiceCall.Avanak\GreenHome.VoiceCall.Avanak.csproj" />
|
||||||
|
<ProjectReference Include="..\GreenHome.AI.DeepSeek\GreenHome.AI.DeepSeek.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
|
|
||||||
<NameOfLastUsedPublishProfile>D:\Data\Projects\php\greenhome\src\GreenHome.Api\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
@GreenHome.Api_HostAddress = http://localhost:5064
|
|
||||||
|
|
||||||
GET {{GreenHome.Api_HostAddress}}/weatherforecast/
|
|
||||||
Accept: application/json
|
|
||||||
|
|
||||||
###
|
|
||||||
1
src/GreenHome.Api/My_StaticFiles/calltest.html
Normal file
1
src/GreenHome.Api/My_StaticFiles/calltest.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
TY09192530212#https://ghback.nabaksoft.ir/My_StaticFiles/output.amr
|
||||||
BIN
src/GreenHome.Api/My_StaticFiles/output.amr
Normal file
BIN
src/GreenHome.Api/My_StaticFiles/output.amr
Normal file
Binary file not shown.
1
src/GreenHome.Api/My_StaticFiles/smsTest.html
Normal file
1
src/GreenHome.Api/My_StaticFiles/smsTest.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
TT09192530212#سلام خوبی
|
||||||
@@ -1,89 +1,124 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using GreenHome.Application;
|
using GreenHome.AI.DeepSeek;
|
||||||
using GreenHome.Infrastructure;
|
using GreenHome.Application;
|
||||||
using GreenHome.Sms.Ippanel;
|
using GreenHome.Infrastructure;
|
||||||
using GreenHome.VoiceCall.Avanak;
|
using GreenHome.Sms.Ippanel;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using GreenHome.VoiceCall.Avanak;
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
// Add services to the container.
|
using Microsoft.Extensions.FileProviders;
|
||||||
builder.Services.AddControllers();
|
using Scalar.AspNetCore;
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
builder.Services.AddSwaggerGen();
|
|
||||||
|
// Add services to the container.
|
||||||
// Application/Infrastructure DI
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddAutoMapper(typeof(GreenHome.Application.MappingProfile));
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddValidatorsFromAssemblyContaining<GreenHome.Application.DeviceDtoValidator>();
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
// CORS for Next.js dev (adjust origins as needed)
|
// Application/Infrastructure DI
|
||||||
const string CorsPolicy = "DefaultCors";
|
builder.Services.AddAutoMapper(typeof(GreenHome.Application.MappingProfile));
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddValidatorsFromAssemblyContaining<GreenHome.Application.DeviceDtoValidator>();
|
||||||
{
|
|
||||||
options.AddPolicy(CorsPolicy, policy =>
|
// CORS Configuration
|
||||||
policy
|
const string CorsPolicy = "DefaultCors";
|
||||||
.WithOrigins(
|
builder.Services.AddCors(options =>
|
||||||
"http://green.nabaksoft.ir",
|
{
|
||||||
"https://green.nabaksoft.ir",
|
options.AddPolicy(CorsPolicy, policy =>
|
||||||
"http://gh1.nabaksoft.ir",
|
{
|
||||||
"https://gh1.nabaksoft.ir",
|
if (builder.Environment.IsDevelopment())
|
||||||
"http://localhost:3000",
|
{
|
||||||
"http://localhost:3000",
|
// در محیط Development همه origin ها مجاز هستند
|
||||||
"http://127.0.0.1:3000",
|
policy
|
||||||
"https://localhost:3000"
|
.AllowAnyOrigin()
|
||||||
)
|
.AllowAnyHeader()
|
||||||
.AllowAnyHeader()
|
.AllowAnyMethod();
|
||||||
.AllowAnyMethod()
|
}
|
||||||
.AllowCredentials()
|
else
|
||||||
);
|
{
|
||||||
});
|
// در محیط Production فقط دامنههای مشخص
|
||||||
|
policy
|
||||||
builder.Services.AddDbContext<GreenHome.Infrastructure.GreenHomeDbContext>(options =>
|
.WithOrigins(
|
||||||
{
|
"http://green.nabaksoft.ir",
|
||||||
options.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
|
"https://green.nabaksoft.ir",
|
||||||
});
|
"http://gh1.nabaksoft.ir",
|
||||||
builder.Services.AddScoped<GreenHome.Application.IDeviceService, GreenHome.Infrastructure.DeviceService>();
|
"https://gh1.nabaksoft.ir"
|
||||||
builder.Services.AddScoped<GreenHome.Application.ITelemetryService, GreenHome.Infrastructure.TelemetryService>();
|
)
|
||||||
builder.Services.AddScoped<GreenHome.Application.IDeviceSettingsService, GreenHome.Infrastructure.DeviceSettingsService>();
|
.AllowAnyHeader()
|
||||||
builder.Services.AddScoped<GreenHome.Application.IAuthService, GreenHome.Infrastructure.AuthService>();
|
.AllowAnyMethod()
|
||||||
builder.Services.AddScoped<GreenHome.Application.IAlertService, GreenHome.Infrastructure.AlertService>();
|
.AllowCredentials();
|
||||||
|
}
|
||||||
// SMS Service Configuration
|
});
|
||||||
builder.Services.AddIppanelSms(builder.Configuration);
|
});
|
||||||
|
|
||||||
// Voice Call Service Configuration
|
builder.Services.AddDbContext<GreenHome.Infrastructure.GreenHomeDbContext>(options =>
|
||||||
builder.Services.AddAvanakVoiceCall(builder.Configuration);
|
{
|
||||||
|
options.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
|
||||||
var app = builder.Build();
|
});
|
||||||
|
builder.Services.AddScoped<GreenHome.Application.IDeviceService, GreenHome.Infrastructure.DeviceService>();
|
||||||
// Apply pending migrations automatically
|
builder.Services.AddScoped<GreenHome.Application.ITelemetryService, GreenHome.Infrastructure.TelemetryService>();
|
||||||
using (var scope = app.Services.CreateScope())
|
builder.Services.AddScoped<GreenHome.Application.IDeviceSettingsService, GreenHome.Infrastructure.DeviceSettingsService>();
|
||||||
{
|
builder.Services.AddScoped<GreenHome.Application.IAuthService, GreenHome.Infrastructure.AuthService>();
|
||||||
var services = scope.ServiceProvider;
|
builder.Services.AddScoped<GreenHome.Application.IAlertService, GreenHome.Infrastructure.AlertService>();
|
||||||
try
|
builder.Services.AddScoped<GreenHome.Application.IAlertConditionService, GreenHome.Infrastructure.AlertConditionService>();
|
||||||
{
|
builder.Services.AddScoped<GreenHome.Application.ISunCalculatorService, GreenHome.Infrastructure.SunCalculatorService>();
|
||||||
var context = services.GetRequiredService<GreenHome.Infrastructure.GreenHomeDbContext>();
|
builder.Services.AddScoped<GreenHome.Application.IAIQueryService, GreenHome.Infrastructure.AIQueryService>();
|
||||||
context.Database.Migrate();
|
builder.Services.AddScoped<GreenHome.Application.IDailyReportService, GreenHome.Infrastructure.DailyReportService>();
|
||||||
}
|
builder.Services.AddScoped<GreenHome.Application.IAlertLogService, GreenHome.Infrastructure.AlertLogService>();
|
||||||
catch (Exception ex)
|
builder.Services.AddScoped<GreenHome.Application.IUserDailyReportService, GreenHome.Infrastructure.UserDailyReportService>();
|
||||||
{
|
builder.Services.AddScoped<GreenHome.Application.IChecklistService, GreenHome.Infrastructure.ChecklistService>();
|
||||||
var logger = services.GetRequiredService<ILogger<Program>>();
|
builder.Services.AddScoped<GreenHome.Application.IMonthlyReportService, GreenHome.Infrastructure.MonthlyReportService>();
|
||||||
logger.LogError(ex, "An error occurred while migrating the database.");
|
builder.Services.AddScoped<GreenHome.Application.IDevicePostService, GreenHome.Infrastructure.DevicePostService>();
|
||||||
}
|
builder.Services.AddScoped<GreenHome.Application.IDeviceTokenService, GreenHome.Infrastructure.DeviceTokenService>();
|
||||||
}
|
|
||||||
|
// SMS Service Configuration
|
||||||
// Configure the HTTP request pipeline.
|
builder.Services.AddIppanelSms(builder.Configuration);
|
||||||
//if (app.Environment.IsDevelopment())
|
|
||||||
{
|
// Voice Call Service Configuration
|
||||||
app.UseSwagger();
|
builder.Services.AddAvanakVoiceCall(builder.Configuration);
|
||||||
app.UseSwaggerUI();
|
|
||||||
}
|
// AI Service Configuration
|
||||||
|
builder.Services.AddDeepSeek(builder.Configuration);
|
||||||
app.UseHttpsRedirection();
|
|
||||||
|
var app = builder.Build();
|
||||||
app.UseCors(CorsPolicy);
|
|
||||||
|
// Apply pending migrations automatically
|
||||||
app.UseAuthorization();
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
app.MapControllers();
|
var services = scope.ServiceProvider;
|
||||||
|
try
|
||||||
app.Run();
|
{
|
||||||
|
var context = services.GetRequiredService<GreenHome.Infrastructure.GreenHomeDbContext>();
|
||||||
|
context.Database.Migrate();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var logger = services.GetRequiredService<ILogger<Program>>();
|
||||||
|
logger.LogError(ex, "An error occurred while migrating the database.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
app.MapOpenApi();
|
||||||
|
app.MapScalarApiReference();
|
||||||
|
if (!app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseCors(CorsPolicy);
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
var provider = new FileExtensionContentTypeProvider();
|
||||||
|
provider.Mappings[".amr"] = "audio/amr";
|
||||||
|
|
||||||
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
FileProvider = new PhysicalFileProvider(
|
||||||
|
Path.Combine(builder.Environment.ContentRootPath, "My_StaticFiles")),
|
||||||
|
RequestPath = "/My_StaticFiles",
|
||||||
|
ContentTypeProvider = provider
|
||||||
|
});
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
|
||||||
-->
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<TimeStampOfAssociatedLegacyPublishXmlFile />
|
|
||||||
<_PublishTargetUrl>D:\Data\Projects\php\greenhome\src\GreenHome.Api\bin\publish</_PublishTargetUrl>
|
|
||||||
<History>True|2025-10-27T10:50:38.6931407Z||;</History>
|
|
||||||
<LastFailureDetails />
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<DestinationConnectionStrings Include="Default">
|
|
||||||
<Value>Server=.%3bDatabase=GreenHomeDb%3bUser Id=sa%3bPassword=qwER12#%24110%3bTrusted_Connection=True%3bMultipleActiveResultSets=true%3bTrustServerCertificate=True</Value>
|
|
||||||
</DestinationConnectionStrings>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
},
|
},
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"applicationUrl": "http://localhost:5064"
|
"applicationUrl": "http://127.0.0.1:5064"
|
||||||
},
|
},
|
||||||
"https": {
|
"https": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
},
|
},
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"applicationUrl": "https://localhost:7274;http://localhost:5064"
|
"applicationUrl": "https://127.0.0.1:7274;http://127.0.0.1:5064"
|
||||||
},
|
},
|
||||||
"IIS Express": {
|
"IIS Express": {
|
||||||
"commandName": "IISExpress",
|
"commandName": "IISExpress",
|
||||||
|
|||||||
@@ -4,5 +4,16 @@
|
|||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Default": "Server=87.107.108.119;TrustServerCertificate=True;Database=GreenHomeDb;User Id=sa;Password=qwER12#$110"
|
||||||
|
},
|
||||||
|
"AvanakVoiceCall": {
|
||||||
|
"Token": "A948B776B90CFD919B0EC60929714136CCB49DDB"
|
||||||
|
},
|
||||||
|
"IppanelSms": {
|
||||||
|
"BaseUrl": "https://edge.ippanel.com/v1",
|
||||||
|
"AuthorizationToken": "YTA1Zjk3N2EtNzkwOC00ZTg5LWFjZmYtZGEyZDAyNjNlZWQxM2Q2ZDVjYWE0MTA2Yzc1NDYzZDY1Y2VkMjlhMzcwNjA=",
|
||||||
|
"DefaultSender": "+983000505"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,16 +2,21 @@
|
|||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning",
|
||||||
|
"GreenHome.VoiceCall.Avanak": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
|
||||||
"Default": "Server=.;Database=GreenHomeDb;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True"
|
|
||||||
},
|
|
||||||
"IppanelSms": {
|
"IppanelSms": {
|
||||||
"BaseUrl": "https://edge.ippanel.com/v1",
|
"BaseUrl": "https://edge.ippanel.com/v1",
|
||||||
"AuthorizationToken": "YTA1Zjk3N2EtNzkwOC00ZTg5LWFjZmYtZGEyZDAyNjNlZWQxM2Q2ZDVjYWE0MTA2Yzc1NDYzZDY1Y2VkMjlhMzcwNjA=",
|
"AuthorizationToken": "YTA1Zjk3N2EtNzkwOC00ZTg5LWFjZmYtZGEyZDAyNjNlZWQxM2Q2ZDVjYWE0MTA2Yzc1NDYzZDY1Y2VkMjlhMzcwNjA=",
|
||||||
"DefaultSender": "+983000505"
|
"DefaultSender": "+983000505"
|
||||||
},
|
},
|
||||||
|
"DeepSeek": {
|
||||||
|
"BaseUrl": "https://api.deepseek.com",
|
||||||
|
"ApiKey": "sk-4470fc1a003a445e92f357dbe123e5a4",
|
||||||
|
"DefaultModel": "deepseek-chat",
|
||||||
|
"DefaultTemperature": 1.0
|
||||||
|
},
|
||||||
|
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// <autogenerated />
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")]
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("GreenHome.Api")]
|
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
|
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("GreenHome.Api")]
|
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("GreenHome.Api")]
|
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
|
||||||
|
|
||||||
// Generated by the MSBuild WriteCodeFragment class.
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
c307d33a16c6447b758cae28ca2fa40d39ada8eff9f6b0aa1055040d6099f1b2
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
is_global = true
|
|
||||||
build_property.TargetFramework = net9.0
|
|
||||||
build_property.TargetPlatformMinVersion =
|
|
||||||
build_property.UsingMicrosoftNETSdkWeb = true
|
|
||||||
build_property.ProjectTypeGuids =
|
|
||||||
build_property.InvariantGlobalization =
|
|
||||||
build_property.PlatformNeutralAssembly =
|
|
||||||
build_property.EnforceExtendedAnalyzerRules =
|
|
||||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
|
||||||
build_property.RootNamespace = GreenHome.Api
|
|
||||||
build_property.RootNamespace = GreenHome.Api
|
|
||||||
build_property.ProjectDir = D:\Data\Projects\php\greenhome\src\GreenHome.Api\
|
|
||||||
build_property.EnableComHosting =
|
|
||||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
|
||||||
build_property.RazorLangVersion = 9.0
|
|
||||||
build_property.SupportLocalizedComponentNames =
|
|
||||||
build_property.GenerateRazorMetadataSourceChecksumAttributes =
|
|
||||||
build_property.MSBuildProjectDirectory = D:\Data\Projects\php\greenhome\src\GreenHome.Api
|
|
||||||
build_property._RazorSourceGeneratorDebug =
|
|
||||||
build_property.EffectiveAnalysisLevelStyle = 9.0
|
|
||||||
build_property.EnableCodeStyleSeverity =
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// <auto-generated/>
|
|
||||||
global using global::Microsoft.AspNetCore.Builder;
|
|
||||||
global using global::Microsoft.AspNetCore.Hosting;
|
|
||||||
global using global::Microsoft.AspNetCore.Http;
|
|
||||||
global using global::Microsoft.AspNetCore.Routing;
|
|
||||||
global using global::Microsoft.Extensions.Configuration;
|
|
||||||
global using global::Microsoft.Extensions.DependencyInjection;
|
|
||||||
global using global::Microsoft.Extensions.Hosting;
|
|
||||||
global using global::Microsoft.Extensions.Logging;
|
|
||||||
global using global::System;
|
|
||||||
global using global::System.Collections.Generic;
|
|
||||||
global using global::System.IO;
|
|
||||||
global using global::System.Linq;
|
|
||||||
global using global::System.Net.Http;
|
|
||||||
global using global::System.Net.Http.Json;
|
|
||||||
global using global::System.Threading;
|
|
||||||
global using global::System.Threading.Tasks;
|
|
||||||
Binary file not shown.
80
src/GreenHome.Application/ChecklistDtos.cs
Normal file
80
src/GreenHome.Application/ChecklistDtos.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public sealed class ChecklistDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public List<ChecklistItemDto> Items { get; set; } = new();
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public int CreatedByUserId { get; set; }
|
||||||
|
public string CreatedByUserName { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ChecklistItemDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public int Order { get; set; }
|
||||||
|
public bool IsRequired { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CreateChecklistRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required int CreatedByUserId { get; set; }
|
||||||
|
public required string Title { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public required List<CreateChecklistItemRequest> Items { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CreateChecklistItemRequest
|
||||||
|
{
|
||||||
|
public required string Title { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public int Order { get; set; }
|
||||||
|
public bool IsRequired { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ChecklistCompletionDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int ChecklistId { get; set; }
|
||||||
|
public string ChecklistTitle { get; set; } = string.Empty;
|
||||||
|
public int CompletedByUserId { get; set; }
|
||||||
|
public string CompletedByUserName { get; set; } = string.Empty;
|
||||||
|
public string PersianDate { get; set; } = string.Empty;
|
||||||
|
public List<ChecklistItemCompletionDto> ItemCompletions { get; set; } = new();
|
||||||
|
public string? Notes { get; set; }
|
||||||
|
public DateTime CompletedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ChecklistItemCompletionDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int ChecklistItemId { get; set; }
|
||||||
|
public string ItemTitle { get; set; } = string.Empty;
|
||||||
|
public bool IsChecked { get; set; }
|
||||||
|
public string? Note { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CompleteChecklistRequest
|
||||||
|
{
|
||||||
|
public required int ChecklistId { get; set; }
|
||||||
|
public required int CompletedByUserId { get; set; }
|
||||||
|
public required string PersianDate { get; set; }
|
||||||
|
public required List<CompleteChecklistItemRequest> ItemCompletions { get; set; }
|
||||||
|
public string? Notes { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CompleteChecklistItemRequest
|
||||||
|
{
|
||||||
|
public required int ChecklistItemId { get; set; }
|
||||||
|
public bool IsChecked { get; set; }
|
||||||
|
public string? Note { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
46
src/GreenHome.Application/DevicePostDtos.cs
Normal file
46
src/GreenHome.Application/DevicePostDtos.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public sealed class DevicePostDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public int AuthorUserId { get; set; }
|
||||||
|
public string AuthorName { get; set; } = string.Empty;
|
||||||
|
public string AuthorFamily { get; set; } = string.Empty;
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public List<DevicePostImageDto> Images { get; set; } = new();
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DevicePostImageDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string FileName { get; set; } = string.Empty;
|
||||||
|
public string FilePath { get; set; } = string.Empty;
|
||||||
|
public string ContentType { get; set; } = string.Empty;
|
||||||
|
public long FileSize { get; set; }
|
||||||
|
public DateTime UploadedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CreateDevicePostRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required int AuthorUserId { get; set; }
|
||||||
|
public required string Content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class UpdateDevicePostRequest
|
||||||
|
{
|
||||||
|
public required int Id { get; set; }
|
||||||
|
public required string Content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DevicePostFilter
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public int? AuthorUserId { get; set; }
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
public int PageSize { get; set; } = 20;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ public sealed class TelemetryDto
|
|||||||
public int PersianYear { get; set; }
|
public int PersianYear { get; set; }
|
||||||
public int PersianMonth { get; set; }
|
public int PersianMonth { get; set; }
|
||||||
public string PersianDate { get; set; } = string.Empty;
|
public string PersianDate { get; set; } = string.Empty;
|
||||||
|
public DateTime ServerTimestampUtc { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class TelemetryFilter
|
public sealed class TelemetryFilter
|
||||||
@@ -117,24 +118,263 @@ public sealed class DeviceSettingsDto
|
|||||||
public int DeviceId { get; set; }
|
public int DeviceId { get; set; }
|
||||||
public string DeviceName { get; set; } = string.Empty;
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
|
||||||
// Temperature settings
|
public string Province { get; set; } = string.Empty;
|
||||||
public decimal DangerMaxTemperature { get; set; }
|
public string City { get; set; } = string.Empty;
|
||||||
public decimal DangerMinTemperature { get; set; }
|
public decimal? Latitude { get; set; }
|
||||||
public decimal MaxTemperature { get; set; }
|
public decimal? Longitude { get; set; }
|
||||||
public decimal MinTemperature { get; set; }
|
|
||||||
|
|
||||||
// Gas settings
|
public string ProductType { get; set; } = string.Empty;
|
||||||
public int MaxGasPPM { get; set; }
|
public int MinimumSmsIntervalMinutes { get; set; } = 15;
|
||||||
public int MinGasPPM { get; set; }
|
public int MinimumCallIntervalMinutes { get; set; } = 60;
|
||||||
|
public decimal? AreaSquareMeters { get; set; }
|
||||||
|
|
||||||
// Light settings
|
public int UploadIntervalMin { get; set; } = 5;
|
||||||
public decimal MaxLux { get; set; }
|
public string DevicePhoneNumber { get; set; } = string.Empty;
|
||||||
public decimal MinLux { get; set; }
|
public Domain.SimCardType? SimCardType { get; set; }
|
||||||
|
public string? TokenCode { get; set; }
|
||||||
// Humidity settings
|
public string? VerificationCode { get; set; }
|
||||||
public decimal MaxHumidityPercent { get; set; }
|
public DateTime? TokenExpiresAt { get; set; }
|
||||||
public decimal MinHumidityPercent { get; set; }
|
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
public DateTime UpdatedAt { get; set; }
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AlertConditionDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
public Domain.AlertNotificationType NotificationType { get; set; }
|
||||||
|
public Domain.AlertTimeType TimeType { get; set; }
|
||||||
|
public int CallCooldownMinutes { get; set; } = 60;
|
||||||
|
public int SmsCooldownMinutes { get; set; } = 15;
|
||||||
|
public bool IsEnabled { get; set; } = true;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
public List<AlertRuleDto> Rules { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AlertRuleDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int AlertConditionId { get; set; }
|
||||||
|
public Domain.SensorType SensorType { get; set; }
|
||||||
|
public Domain.ComparisonType ComparisonType { get; set; }
|
||||||
|
public decimal Value1 { get; set; }
|
||||||
|
public decimal? Value2 { get; set; }
|
||||||
|
public int Order { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CreateAlertConditionRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required Domain.AlertNotificationType NotificationType { get; set; }
|
||||||
|
public required Domain.AlertTimeType TimeType { get; set; }
|
||||||
|
public int CallCooldownMinutes { get; set; } = 60;
|
||||||
|
public int SmsCooldownMinutes { get; set; } = 15;
|
||||||
|
public bool IsEnabled { get; set; } = true;
|
||||||
|
public required List<CreateAlertRuleRequest> Rules { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CreateAlertRuleRequest
|
||||||
|
{
|
||||||
|
public required Domain.SensorType SensorType { get; set; }
|
||||||
|
public required Domain.ComparisonType ComparisonType { get; set; }
|
||||||
|
public required decimal Value1 { get; set; }
|
||||||
|
public decimal? Value2 { get; set; }
|
||||||
|
public int Order { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class UpdateAlertConditionRequest
|
||||||
|
{
|
||||||
|
public required int Id { get; set; }
|
||||||
|
public required Domain.AlertNotificationType NotificationType { get; set; }
|
||||||
|
public required Domain.AlertTimeType TimeType { get; set; }
|
||||||
|
public int CallCooldownMinutes { get; set; } = 60;
|
||||||
|
public int SmsCooldownMinutes { get; set; } = 15;
|
||||||
|
public bool IsEnabled { get; set; } = true;
|
||||||
|
public required List<CreateAlertRuleRequest> Rules { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DailyReportRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required string PersianDate { get; set; } // yyyy/MM/dd
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DailyReportResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
public string PersianDate { get; set; } = string.Empty;
|
||||||
|
public string Analysis { get; set; } = string.Empty;
|
||||||
|
public int RecordCount { get; set; }
|
||||||
|
public int SampledRecordCount { get; set; }
|
||||||
|
public int TotalTokens { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public bool FromCache { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class WeeklyAnalysisRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required string StartDate { get; set; } // yyyy/MM/dd
|
||||||
|
public required string EndDate { get; set; } // yyyy/MM/dd
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MonthlyAnalysisRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required int Year { get; set; }
|
||||||
|
public required int Month { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AlertLogDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string UserMobile { get; set; } = string.Empty;
|
||||||
|
public int? AlertConditionId { get; set; }
|
||||||
|
public Domain.AlertType AlertType { get; set; }
|
||||||
|
public Domain.AlertNotificationType NotificationType { get; set; }
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
public Domain.AlertStatus Status { get; set; }
|
||||||
|
public string? ErrorMessage { get; set; }
|
||||||
|
public string PhoneNumber { get; set; } = string.Empty;
|
||||||
|
public DateTime SentAt { get; set; }
|
||||||
|
public long ProcessingTimeMs { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class AlertLogFilter
|
||||||
|
{
|
||||||
|
public int? DeviceId { get; set; }
|
||||||
|
public int? UserId { get; set; }
|
||||||
|
public Domain.AlertType? AlertType { get; set; }
|
||||||
|
public Domain.AlertStatus? Status { get; set; }
|
||||||
|
public DateTime? StartDate { get; set; }
|
||||||
|
public DateTime? EndDate { get; set; }
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
public int PageSize { get; set; } = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class UserDailyReportDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string UserFamily { get; set; } = string.Empty;
|
||||||
|
public string PersianDate { get; set; } = string.Empty;
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Observations { get; set; } = string.Empty;
|
||||||
|
public string Operations { get; set; } = string.Empty;
|
||||||
|
public string? Notes { get; set; }
|
||||||
|
public List<ReportImageDto> Images { get; set; } = new();
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ReportImageDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string FileName { get; set; } = string.Empty;
|
||||||
|
public string FilePath { get; set; } = string.Empty;
|
||||||
|
public string ContentType { get; set; } = string.Empty;
|
||||||
|
public long FileSize { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public DateTime UploadedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class CreateUserDailyReportRequest
|
||||||
|
{
|
||||||
|
public required int DeviceId { get; set; }
|
||||||
|
public required int UserId { get; set; }
|
||||||
|
public required string PersianDate { get; set; }
|
||||||
|
public required string Title { get; set; }
|
||||||
|
public required string Observations { get; set; }
|
||||||
|
public required string Operations { get; set; }
|
||||||
|
public string? Notes { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class UpdateUserDailyReportRequest
|
||||||
|
{
|
||||||
|
public required int Id { get; set; }
|
||||||
|
public required string Title { get; set; }
|
||||||
|
public required string Observations { get; set; }
|
||||||
|
public required string Operations { get; set; }
|
||||||
|
public string? Notes { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class UserDailyReportFilter
|
||||||
|
{
|
||||||
|
public int? DeviceId { get; set; }
|
||||||
|
public int? UserId { get; set; }
|
||||||
|
public string? PersianDate { get; set; }
|
||||||
|
public int? Year { get; set; }
|
||||||
|
public int? Month { get; set; }
|
||||||
|
public int Page { get; set; } = 1;
|
||||||
|
public int PageSize { get; set; } = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTOs برای مدیریت توکن دستگاه
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// درخواست دریافت فاصله زمانی آپلود
|
||||||
|
/// </summary>
|
||||||
|
public sealed class GetUploadIntervalRequest
|
||||||
|
{
|
||||||
|
public int? DeviceId { get; set; }
|
||||||
|
public string? DevicePhoneNumber { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پاسخ دریافت فاصله زمانی آپلود
|
||||||
|
/// </summary>
|
||||||
|
public sealed class GetUploadIntervalResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string? Message { get; set; }
|
||||||
|
public int? UploadIntervalMin { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// درخواست دریافت توکن دستگاه
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RequestDeviceTokenRequest
|
||||||
|
{
|
||||||
|
public required string DevicePhoneNumber { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پاسخ دریافت توکن دستگاه
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RequestDeviceTokenResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string? Message { get; set; }
|
||||||
|
public string? TokenCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// درخواست تایید توکن دستگاه
|
||||||
|
/// </summary>
|
||||||
|
public sealed class VerifyDeviceTokenRequest
|
||||||
|
{
|
||||||
|
public required string DevicePhoneNumber { get; set; }
|
||||||
|
public required string VerificationCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پاسخ تایید توکن دستگاه
|
||||||
|
/// </summary>
|
||||||
|
public sealed class VerifyDeviceTokenResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string? Message { get; set; }
|
||||||
|
public string? EncodedSettings { get; set; }
|
||||||
}
|
}
|
||||||
59
src/GreenHome.Application/IAIQueryService.cs
Normal file
59
src/GreenHome.Application/IAIQueryService.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using GreenHome.Domain;
|
||||||
|
|
||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Service for managing AI queries and their history
|
||||||
|
/// </summary>
|
||||||
|
public interface IAIQueryService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Saves an AI query to the database
|
||||||
|
/// </summary>
|
||||||
|
Task<AIQuery> SaveQueryAsync(AIQuery query, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets AI query history for a specific device
|
||||||
|
/// </summary>
|
||||||
|
Task<List<AIQuery>> GetDeviceQueriesAsync(int deviceId, int take = 50, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets AI query history for a specific user
|
||||||
|
/// </summary>
|
||||||
|
Task<List<AIQuery>> GetUserQueriesAsync(int userId, int take = 50, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets total token usage for a device
|
||||||
|
/// </summary>
|
||||||
|
Task<int> GetDeviceTotalTokensAsync(int deviceId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets total token usage for a user
|
||||||
|
/// </summary>
|
||||||
|
Task<int> GetUserTotalTokensAsync(int userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets recent queries (all)
|
||||||
|
/// </summary>
|
||||||
|
Task<List<AIQuery>> GetRecentQueriesAsync(int take = 20, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets query statistics
|
||||||
|
/// </summary>
|
||||||
|
Task<AIQueryStats> GetStatsAsync(CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Statistics about AI queries
|
||||||
|
/// </summary>
|
||||||
|
public class AIQueryStats
|
||||||
|
{
|
||||||
|
public int TotalQueries { get; set; }
|
||||||
|
public int TotalTokensUsed { get; set; }
|
||||||
|
public int TotalPromptTokens { get; set; }
|
||||||
|
public int TotalCompletionTokens { get; set; }
|
||||||
|
public double AverageResponseTimeMs { get; set; }
|
||||||
|
public int TodayQueries { get; set; }
|
||||||
|
public int TodayTokens { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
12
src/GreenHome.Application/IAlertConditionService.cs
Normal file
12
src/GreenHome.Application/IAlertConditionService.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IAlertConditionService
|
||||||
|
{
|
||||||
|
Task<IReadOnlyList<AlertConditionDto>> GetByDeviceIdAsync(int deviceId, CancellationToken cancellationToken);
|
||||||
|
Task<AlertConditionDto?> GetByIdAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> CreateAsync(CreateAlertConditionRequest request, CancellationToken cancellationToken);
|
||||||
|
Task UpdateAsync(UpdateAlertConditionRequest request, CancellationToken cancellationToken);
|
||||||
|
Task DeleteAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<bool> ToggleEnabledAsync(int id, bool isEnabled, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
9
src/GreenHome.Application/IAlertLogService.cs
Normal file
9
src/GreenHome.Application/IAlertLogService.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IAlertLogService
|
||||||
|
{
|
||||||
|
Task<PagedResult<AlertLogDto>> GetAlertLogsAsync(AlertLogFilter filter, CancellationToken cancellationToken);
|
||||||
|
Task<AlertLogDto?> GetAlertLogByIdAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> CreateAlertLogAsync(AlertLogDto dto, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -3,5 +3,6 @@ namespace GreenHome.Application;
|
|||||||
public interface IAlertService
|
public interface IAlertService
|
||||||
{
|
{
|
||||||
Task CheckAndSendAlertsAsync(int deviceId, TelemetryDto telemetry, CancellationToken cancellationToken);
|
Task CheckAndSendAlertsAsync(int deviceId, TelemetryDto telemetry, CancellationToken cancellationToken);
|
||||||
|
Task SendPowerOutageAlertAsync(int deviceId, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
src/GreenHome.Application/IChecklistService.cs
Normal file
12
src/GreenHome.Application/IChecklistService.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IChecklistService
|
||||||
|
{
|
||||||
|
Task<ChecklistDto?> GetActiveChecklistByDeviceIdAsync(int deviceId, CancellationToken cancellationToken);
|
||||||
|
Task<List<ChecklistDto>> GetChecklistsByDeviceIdAsync(int deviceId, CancellationToken cancellationToken);
|
||||||
|
Task<ChecklistDto?> GetChecklistByIdAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> CreateChecklistAsync(CreateChecklistRequest request, CancellationToken cancellationToken);
|
||||||
|
Task<List<ChecklistCompletionDto>> GetCompletionsByChecklistIdAsync(int checklistId, CancellationToken cancellationToken);
|
||||||
|
Task<int> CompleteChecklistAsync(CompleteChecklistRequest request, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
17
src/GreenHome.Application/IDailyReportService.cs
Normal file
17
src/GreenHome.Application/IDailyReportService.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IDailyReportService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or generates a daily analysis report for a device on a specific date
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Request containing device ID and Persian date</param>
|
||||||
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
|
/// <returns>Daily report with AI analysis</returns>
|
||||||
|
Task<DailyReportResponse> GetOrCreateDailyReportAsync(DailyReportRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<DailyReportResponse> GetWeeklyAnalysisAsync(WeeklyAnalysisRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<DailyReportResponse> GetMonthlyAnalysisAsync(MonthlyAnalysisRequest request, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
14
src/GreenHome.Application/IDevicePostService.cs
Normal file
14
src/GreenHome.Application/IDevicePostService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IDevicePostService
|
||||||
|
{
|
||||||
|
Task<PagedResult<DevicePostDto>> GetPostsAsync(DevicePostFilter filter, CancellationToken cancellationToken);
|
||||||
|
Task<DevicePostDto?> GetPostByIdAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> CreatePostAsync(CreateDevicePostRequest request, CancellationToken cancellationToken);
|
||||||
|
Task UpdatePostAsync(UpdateDevicePostRequest request, CancellationToken cancellationToken);
|
||||||
|
Task DeletePostAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> AddImageToPostAsync(int postId, string fileName, string filePath, string contentType, long fileSize, CancellationToken cancellationToken);
|
||||||
|
Task DeleteImageAsync(int imageId, CancellationToken cancellationToken);
|
||||||
|
Task<bool> CanUserAccessDeviceAsync(int userId, int deviceId, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
23
src/GreenHome.Application/IDeviceTokenService.cs
Normal file
23
src/GreenHome.Application/IDeviceTokenService.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// سرویس مدیریت توکن و تنظیمات دستگاه
|
||||||
|
/// </summary>
|
||||||
|
public interface IDeviceTokenService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت فاصله زمانی آپلود بر اساس شماره تلفن یا شناسه دستگاه
|
||||||
|
/// </summary>
|
||||||
|
Task<GetUploadIntervalResponse> GetUploadIntervalAsync(GetUploadIntervalRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// درخواست توکن دستگاه (تولید و ارسال کد)
|
||||||
|
/// </summary>
|
||||||
|
Task<RequestDeviceTokenResponse> RequestDeviceTokenAsync(RequestDeviceTokenRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// تایید توکن دستگاه (ارسال تنظیمات)
|
||||||
|
/// </summary>
|
||||||
|
Task<VerifyDeviceTokenResponse> VerifyDeviceTokenAsync(VerifyDeviceTokenRequest request, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
45
src/GreenHome.Application/IMonthlyReportService.cs
Normal file
45
src/GreenHome.Application/IMonthlyReportService.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IMonthlyReportService
|
||||||
|
{
|
||||||
|
Task<MonthlyReportDto> GetMonthlyReportAsync(int deviceId, int year, int month, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class MonthlyReportDto
|
||||||
|
{
|
||||||
|
public int DeviceId { get; set; }
|
||||||
|
public string DeviceName { get; set; } = string.Empty;
|
||||||
|
public int Year { get; set; }
|
||||||
|
public int Month { get; set; }
|
||||||
|
|
||||||
|
// Alert Statistics
|
||||||
|
public int TotalAlerts { get; set; }
|
||||||
|
public int SmsAlerts { get; set; }
|
||||||
|
public int CallAlerts { get; set; }
|
||||||
|
public int SuccessfulAlerts { get; set; }
|
||||||
|
public int FailedAlerts { get; set; }
|
||||||
|
public int PowerOutageAlerts { get; set; }
|
||||||
|
|
||||||
|
// Telemetry Statistics
|
||||||
|
public int TotalTelemetryRecords { get; set; }
|
||||||
|
public decimal AverageTemperature { get; set; }
|
||||||
|
public decimal MinTemperature { get; set; }
|
||||||
|
public decimal MaxTemperature { get; set; }
|
||||||
|
public decimal AverageHumidity { get; set; }
|
||||||
|
public decimal MinHumidity { get; set; }
|
||||||
|
public decimal MaxHumidity { get; set; }
|
||||||
|
public decimal AverageLux { get; set; }
|
||||||
|
public int AverageGasPPM { get; set; }
|
||||||
|
public int MaxGasPPM { get; set; }
|
||||||
|
|
||||||
|
// User Activity
|
||||||
|
public int UserDailyReportsCount { get; set; }
|
||||||
|
public int ChecklistCompletionsCount { get; set; }
|
||||||
|
public int DailyAnalysesCount { get; set; }
|
||||||
|
|
||||||
|
// Performance Summary
|
||||||
|
public string PerformanceSummary { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public DateTime GeneratedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
14
src/GreenHome.Application/ISunCalculatorService.cs
Normal file
14
src/GreenHome.Application/ISunCalculatorService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface ISunCalculatorService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// بررسی میکند که آیا زمان داده شده در روز است یا شب
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateTime">زمان UTC</param>
|
||||||
|
/// <param name="latitude">عرض جغرافیایی</param>
|
||||||
|
/// <param name="longitude">طول جغرافیایی</param>
|
||||||
|
/// <returns>true اگر روز باشد، false اگر شب باشد</returns>
|
||||||
|
bool IsDaytime(DateTime dateTime, decimal latitude, decimal longitude);
|
||||||
|
}
|
||||||
|
|
||||||
13
src/GreenHome.Application/IUserDailyReportService.cs
Normal file
13
src/GreenHome.Application/IUserDailyReportService.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace GreenHome.Application;
|
||||||
|
|
||||||
|
public interface IUserDailyReportService
|
||||||
|
{
|
||||||
|
Task<PagedResult<UserDailyReportDto>> GetReportsAsync(UserDailyReportFilter filter, CancellationToken cancellationToken);
|
||||||
|
Task<UserDailyReportDto?> GetReportByIdAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> CreateReportAsync(CreateUserDailyReportRequest request, CancellationToken cancellationToken);
|
||||||
|
Task UpdateReportAsync(UpdateUserDailyReportRequest request, CancellationToken cancellationToken);
|
||||||
|
Task DeleteReportAsync(int id, CancellationToken cancellationToken);
|
||||||
|
Task<int> AddImageToReportAsync(int reportId, string fileName, string filePath, string contentType, long fileSize, string? description, CancellationToken cancellationToken);
|
||||||
|
Task DeleteImageAsync(int imageId, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -21,6 +21,51 @@ public sealed class MappingProfile : Profile
|
|||||||
.ReverseMap()
|
.ReverseMap()
|
||||||
.ForMember(dest => dest.Device, opt => opt.Ignore());
|
.ForMember(dest => dest.Device, opt => opt.Ignore());
|
||||||
|
|
||||||
|
CreateMap<Domain.AlertCondition, AlertConditionDto>()
|
||||||
|
.ForMember(dest => dest.DeviceName, opt => opt.MapFrom(src => src.Device.DeviceName))
|
||||||
|
.ReverseMap()
|
||||||
|
.ForMember(dest => dest.Device, opt => opt.Ignore());
|
||||||
|
|
||||||
|
CreateMap<Domain.AlertRule, AlertRuleDto>().ReverseMap()
|
||||||
|
.ForMember(dest => dest.AlertCondition, opt => opt.Ignore());
|
||||||
|
|
||||||
|
CreateMap<CreateAlertRuleRequest, Domain.AlertRule>();
|
||||||
|
|
||||||
CreateMap<Domain.User, UserDto>().ReverseMap();
|
CreateMap<Domain.User, UserDto>().ReverseMap();
|
||||||
|
|
||||||
|
CreateMap<Domain.AlertLog, AlertLogDto>()
|
||||||
|
.ForMember(dest => dest.DeviceName, opt => opt.MapFrom(src => src.Device.DeviceName))
|
||||||
|
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.User.Name))
|
||||||
|
.ForMember(dest => dest.UserMobile, opt => opt.MapFrom(src => src.User.Mobile))
|
||||||
|
.ReverseMap()
|
||||||
|
.ForMember(dest => dest.Device, opt => opt.Ignore())
|
||||||
|
.ForMember(dest => dest.User, opt => opt.Ignore())
|
||||||
|
.ForMember(dest => dest.AlertCondition, opt => opt.Ignore());
|
||||||
|
|
||||||
|
CreateMap<Domain.UserDailyReport, UserDailyReportDto>()
|
||||||
|
.ForMember(dest => dest.DeviceName, opt => opt.MapFrom(src => src.Device.DeviceName))
|
||||||
|
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.User.Name))
|
||||||
|
.ForMember(dest => dest.UserFamily, opt => opt.MapFrom(src => src.User.Family));
|
||||||
|
|
||||||
|
CreateMap<Domain.ReportImage, ReportImageDto>();
|
||||||
|
|
||||||
|
CreateMap<Domain.Checklist, ChecklistDto>()
|
||||||
|
.ForMember(dest => dest.DeviceName, opt => opt.MapFrom(src => src.Device.DeviceName))
|
||||||
|
.ForMember(dest => dest.CreatedByUserName, opt => opt.MapFrom(src => src.CreatedByUser.Name + " " + src.CreatedByUser.Family));
|
||||||
|
|
||||||
|
CreateMap<Domain.ChecklistItem, ChecklistItemDto>();
|
||||||
|
|
||||||
|
CreateMap<Domain.ChecklistCompletion, ChecklistCompletionDto>()
|
||||||
|
.ForMember(dest => dest.ChecklistTitle, opt => opt.MapFrom(src => src.Checklist.Title))
|
||||||
|
.ForMember(dest => dest.CompletedByUserName, opt => opt.MapFrom(src => src.CompletedByUser.Name + " " + src.CompletedByUser.Family));
|
||||||
|
|
||||||
|
CreateMap<Domain.ChecklistItemCompletion, ChecklistItemCompletionDto>()
|
||||||
|
.ForMember(dest => dest.ItemTitle, opt => opt.MapFrom(src => src.ChecklistItem.Title));
|
||||||
|
|
||||||
|
CreateMap<Domain.DevicePost, DevicePostDto>()
|
||||||
|
.ForMember(dest => dest.AuthorName, opt => opt.MapFrom(src => src.AuthorUser.Name))
|
||||||
|
.ForMember(dest => dest.AuthorFamily, opt => opt.MapFrom(src => src.AuthorUser.Family));
|
||||||
|
|
||||||
|
CreateMap<Domain.DevicePostImage, DevicePostImageDto>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
{
|
|
||||||
"runtimeTarget": {
|
|
||||||
"name": ".NETCoreApp,Version=v9.0",
|
|
||||||
"signature": ""
|
|
||||||
},
|
|
||||||
"compilationOptions": {},
|
|
||||||
"targets": {
|
|
||||||
".NETCoreApp,Version=v9.0": {
|
|
||||||
"GreenHome.Application/1.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"AutoMapper": "12.0.1",
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
|
||||||
"FluentValidation": "11.9.1",
|
|
||||||
"FluentValidation.DependencyInjectionExtensions": "11.9.1",
|
|
||||||
"GreenHome.Domain": "1.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"GreenHome.Application.dll": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AutoMapper/12.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.CSharp": "4.7.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/AutoMapper.dll": {
|
|
||||||
"assemblyVersion": "12.0.0.0",
|
|
||||||
"fileVersion": "12.0.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection/12.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"AutoMapper": "12.0.1",
|
|
||||||
"Microsoft.Extensions.Options": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/AutoMapper.Extensions.Microsoft.DependencyInjection.dll": {
|
|
||||||
"assemblyVersion": "12.0.0.0",
|
|
||||||
"fileVersion": "12.0.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"FluentValidation/11.9.1": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net8.0/FluentValidation.dll": {
|
|
||||||
"assemblyVersion": "11.0.0.0",
|
|
||||||
"fileVersion": "11.9.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"FluentValidation.DependencyInjectionExtensions/11.9.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"FluentValidation": "11.9.1",
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/FluentValidation.DependencyInjectionExtensions.dll": {
|
|
||||||
"assemblyVersion": "11.0.0.0",
|
|
||||||
"fileVersion": "11.9.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.CSharp/4.7.0": {},
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "6.0.0.0",
|
|
||||||
"fileVersion": "6.0.21.52210"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Options/6.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
|
||||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/Microsoft.Extensions.Options.dll": {
|
|
||||||
"assemblyVersion": "6.0.0.0",
|
|
||||||
"fileVersion": "6.0.21.52210"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Primitives/6.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.Extensions.Primitives.dll": {
|
|
||||||
"assemblyVersion": "6.0.0.0",
|
|
||||||
"fileVersion": "6.0.21.52210"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {},
|
|
||||||
"GreenHome.Domain/1.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"GreenHome.Domain.dll": {
|
|
||||||
"assemblyVersion": "1.0.0",
|
|
||||||
"fileVersion": "1.0.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libraries": {
|
|
||||||
"GreenHome.Application/1.0.0": {
|
|
||||||
"type": "project",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
},
|
|
||||||
"AutoMapper/12.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-hvV62vl6Hp/WfQ24yzo3Co9+OPl8wH8hApwVtgWpiAynVJkUcs7xvehnSftawL8Pe8FrPffBRM3hwzLQqWDNjA==",
|
|
||||||
"path": "automapper/12.0.1",
|
|
||||||
"hashPath": "automapper.12.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection/12.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-+g/K+Vpe3gGMKGzjslMOdqNlkikScDjWfVvmWTayrDHaG/n2pPmFBMa+jKX1r/h6BDGFdkyRjAuhFE3ykW+r1g==",
|
|
||||||
"path": "automapper.extensions.microsoft.dependencyinjection/12.0.1",
|
|
||||||
"hashPath": "automapper.extensions.microsoft.dependencyinjection.12.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"FluentValidation/11.9.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-C+PqISSMdlOZZJx0Hx25atW32tv4vbpsaiQB+PLjK+ZGLzOFuHl1fUJ3Lny77mIZ31ZtYtNG0JgUjxa3wwLsWg==",
|
|
||||||
"path": "fluentvalidation/11.9.1",
|
|
||||||
"hashPath": "fluentvalidation.11.9.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"FluentValidation.DependencyInjectionExtensions/11.9.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-3jJbFcCWhiXhrCKFPjKihzccmosv+CleYewd2zEYS4aaUHx9zQSgOvkYbWUGTbDwJ5j2nDWE0Pr1EQ2xY4pryg==",
|
|
||||||
"path": "fluentvalidation.dependencyinjectionextensions/11.9.1",
|
|
||||||
"hashPath": "fluentvalidation.dependencyinjectionextensions.11.9.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.CSharp/4.7.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
|
|
||||||
"path": "microsoft.csharp/4.7.0",
|
|
||||||
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==",
|
|
||||||
"path": "microsoft.extensions.dependencyinjection.abstractions/6.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Options/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
|
|
||||||
"path": "microsoft.extensions.options/6.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.options.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Primitives/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
|
||||||
"path": "microsoft.extensions.primitives/6.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.primitives.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
|
||||||
"path": "system.runtime.compilerservices.unsafe/6.0.0",
|
|
||||||
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"GreenHome.Domain/1.0.0": {
|
|
||||||
"type": "project",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,182 +0,0 @@
|
|||||||
{
|
|
||||||
"runtimeTarget": {
|
|
||||||
"name": ".NETCoreApp,Version=v9.0",
|
|
||||||
"signature": ""
|
|
||||||
},
|
|
||||||
"compilationOptions": {},
|
|
||||||
"targets": {
|
|
||||||
".NETCoreApp,Version=v9.0": {
|
|
||||||
"GreenHome.Application/1.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"AutoMapper": "12.0.1",
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
|
||||||
"FluentValidation": "11.9.1",
|
|
||||||
"FluentValidation.DependencyInjectionExtensions": "11.9.1",
|
|
||||||
"GreenHome.Domain": "1.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"GreenHome.Application.dll": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AutoMapper/12.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.CSharp": "4.7.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/AutoMapper.dll": {
|
|
||||||
"assemblyVersion": "12.0.0.0",
|
|
||||||
"fileVersion": "12.0.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection/12.0.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"AutoMapper": "12.0.1",
|
|
||||||
"Microsoft.Extensions.Options": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/AutoMapper.Extensions.Microsoft.DependencyInjection.dll": {
|
|
||||||
"assemblyVersion": "12.0.0.0",
|
|
||||||
"fileVersion": "12.0.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"FluentValidation/11.9.1": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net8.0/FluentValidation.dll": {
|
|
||||||
"assemblyVersion": "11.0.0.0",
|
|
||||||
"fileVersion": "11.9.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"FluentValidation.DependencyInjectionExtensions/11.9.1": {
|
|
||||||
"dependencies": {
|
|
||||||
"FluentValidation": "11.9.1",
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/FluentValidation.DependencyInjectionExtensions.dll": {
|
|
||||||
"assemblyVersion": "11.0.0.0",
|
|
||||||
"fileVersion": "11.9.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.CSharp/4.7.0": {},
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
|
|
||||||
"assemblyVersion": "6.0.0.0",
|
|
||||||
"fileVersion": "6.0.21.52210"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Options/6.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
|
||||||
"Microsoft.Extensions.Primitives": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/netstandard2.1/Microsoft.Extensions.Options.dll": {
|
|
||||||
"assemblyVersion": "6.0.0.0",
|
|
||||||
"fileVersion": "6.0.21.52210"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Primitives/6.0.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
|
||||||
},
|
|
||||||
"runtime": {
|
|
||||||
"lib/net6.0/Microsoft.Extensions.Primitives.dll": {
|
|
||||||
"assemblyVersion": "6.0.0.0",
|
|
||||||
"fileVersion": "6.0.21.52210"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {},
|
|
||||||
"GreenHome.Domain/1.0.0": {
|
|
||||||
"runtime": {
|
|
||||||
"GreenHome.Domain.dll": {
|
|
||||||
"assemblyVersion": "1.0.0",
|
|
||||||
"fileVersion": "1.0.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libraries": {
|
|
||||||
"GreenHome.Application/1.0.0": {
|
|
||||||
"type": "project",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
},
|
|
||||||
"AutoMapper/12.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-hvV62vl6Hp/WfQ24yzo3Co9+OPl8wH8hApwVtgWpiAynVJkUcs7xvehnSftawL8Pe8FrPffBRM3hwzLQqWDNjA==",
|
|
||||||
"path": "automapper/12.0.1",
|
|
||||||
"hashPath": "automapper.12.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection/12.0.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-+g/K+Vpe3gGMKGzjslMOdqNlkikScDjWfVvmWTayrDHaG/n2pPmFBMa+jKX1r/h6BDGFdkyRjAuhFE3ykW+r1g==",
|
|
||||||
"path": "automapper.extensions.microsoft.dependencyinjection/12.0.1",
|
|
||||||
"hashPath": "automapper.extensions.microsoft.dependencyinjection.12.0.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"FluentValidation/11.9.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-C+PqISSMdlOZZJx0Hx25atW32tv4vbpsaiQB+PLjK+ZGLzOFuHl1fUJ3Lny77mIZ31ZtYtNG0JgUjxa3wwLsWg==",
|
|
||||||
"path": "fluentvalidation/11.9.1",
|
|
||||||
"hashPath": "fluentvalidation.11.9.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"FluentValidation.DependencyInjectionExtensions/11.9.1": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-3jJbFcCWhiXhrCKFPjKihzccmosv+CleYewd2zEYS4aaUHx9zQSgOvkYbWUGTbDwJ5j2nDWE0Pr1EQ2xY4pryg==",
|
|
||||||
"path": "fluentvalidation.dependencyinjectionextensions/11.9.1",
|
|
||||||
"hashPath": "fluentvalidation.dependencyinjectionextensions.11.9.1.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.CSharp/4.7.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
|
|
||||||
"path": "microsoft.csharp/4.7.0",
|
|
||||||
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==",
|
|
||||||
"path": "microsoft.extensions.dependencyinjection.abstractions/6.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Options/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
|
|
||||||
"path": "microsoft.extensions.options/6.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.options.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Extensions.Primitives/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
|
||||||
"path": "microsoft.extensions.primitives/6.0.0",
|
|
||||||
"hashPath": "microsoft.extensions.primitives.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
|
||||||
"path": "system.runtime.compilerservices.unsafe/6.0.0",
|
|
||||||
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"GreenHome.Domain/1.0.0": {
|
|
||||||
"type": "project",
|
|
||||||
"serviceable": false,
|
|
||||||
"sha512": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +0,0 @@
|
|||||||
// <autogenerated />
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")]
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("GreenHome.Application")]
|
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
|
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("GreenHome.Application")]
|
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("GreenHome.Application")]
|
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
|
||||||
|
|
||||||
// Generated by the MSBuild WriteCodeFragment class.
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
87754e227edff18d2f8cbf8e8c2800efea9ccd001b65fda01d41cf5fccfdcdf2
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
is_global = true
|
|
||||||
build_property.TargetFramework = net9.0
|
|
||||||
build_property.TargetPlatformMinVersion =
|
|
||||||
build_property.UsingMicrosoftNETSdkWeb =
|
|
||||||
build_property.ProjectTypeGuids =
|
|
||||||
build_property.InvariantGlobalization =
|
|
||||||
build_property.PlatformNeutralAssembly =
|
|
||||||
build_property.EnforceExtendedAnalyzerRules =
|
|
||||||
build_property._SupportedPlatformList = Linux,macOS,Windows
|
|
||||||
build_property.RootNamespace = GreenHome.Application
|
|
||||||
build_property.ProjectDir = D:\Data\Projects\php\greenhome\src\GreenHome.Application\
|
|
||||||
build_property.EnableComHosting =
|
|
||||||
build_property.EnableGeneratedComInterfaceComImportInterop =
|
|
||||||
build_property.EffectiveAnalysisLevelStyle = 9.0
|
|
||||||
build_property.EnableCodeStyleSeverity =
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// <auto-generated/>
|
|
||||||
global using global::System;
|
|
||||||
global using global::System.Collections.Generic;
|
|
||||||
global using global::System.IO;
|
|
||||||
global using global::System.Linq;
|
|
||||||
global using global::System.Net.Http;
|
|
||||||
global using global::System.Threading;
|
|
||||||
global using global::System.Threading.Tasks;
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
1075aa3c2ab89cd2b2a483df9b8b5b5090e6adb783dab67ddd44a3d6b31d56cd
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.csproj.AssemblyReference.cache
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.GeneratedMSBuildEditorConfig.editorconfig
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.AssemblyInfoInputs.cache
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.AssemblyInfo.cs
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.csproj.CoreCompileInputs.cache
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\bin\Debug\net9.0\GreenHome.Application.deps.json
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\bin\Debug\net9.0\GreenHome.Application.dll
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\bin\Debug\net9.0\GreenHome.Application.pdb
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\bin\Debug\net9.0\GreenHome.Domain.dll
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\bin\Debug\net9.0\GreenHome.Domain.pdb
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHom.4051C179.Up2Date
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.dll
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\refint\GreenHome.Application.dll
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\GreenHome.Application.pdb
|
|
||||||
D:\Data\Projects\php\greenhome\src\GreenHome.Application\obj\Debug\net9.0\ref\GreenHome.Application.dll
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,170 +0,0 @@
|
|||||||
{
|
|
||||||
"format": 1,
|
|
||||||
"restore": {
|
|
||||||
"D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\GreenHome.Application.csproj": {}
|
|
||||||
},
|
|
||||||
"projects": {
|
|
||||||
"D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\GreenHome.Application.csproj": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"restore": {
|
|
||||||
"projectUniqueName": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\GreenHome.Application.csproj",
|
|
||||||
"projectName": "GreenHome.Application",
|
|
||||||
"projectPath": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\GreenHome.Application.csproj",
|
|
||||||
"packagesPath": "C:\\Users\\Mohammad\\.nuget\\packages\\",
|
|
||||||
"outputPath": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Application\\obj\\",
|
|
||||||
"projectStyle": "PackageReference",
|
|
||||||
"fallbackFolders": [
|
|
||||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
|
||||||
],
|
|
||||||
"configFilePaths": [
|
|
||||||
"C:\\Users\\Mohammad\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
|
||||||
],
|
|
||||||
"originalTargetFrameworks": [
|
|
||||||
"net9.0"
|
|
||||||
],
|
|
||||||
"sources": {
|
|
||||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
|
||||||
"https://api.nuget.org/v3/index.json": {}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net9.0": {
|
|
||||||
"targetAlias": "net9.0",
|
|
||||||
"projectReferences": {
|
|
||||||
"D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\GreenHome.Domain.csproj": {
|
|
||||||
"projectPath": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\GreenHome.Domain.csproj"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"warningProperties": {
|
|
||||||
"warnAsError": [
|
|
||||||
"NU1605"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"restoreAuditProperties": {
|
|
||||||
"enableAudit": "true",
|
|
||||||
"auditLevel": "low",
|
|
||||||
"auditMode": "direct"
|
|
||||||
},
|
|
||||||
"SdkAnalysisLevel": "9.0.100"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net9.0": {
|
|
||||||
"targetAlias": "net9.0",
|
|
||||||
"dependencies": {
|
|
||||||
"AutoMapper": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[12.0.1, )"
|
|
||||||
},
|
|
||||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[12.0.1, )"
|
|
||||||
},
|
|
||||||
"FluentValidation": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[11.9.1, )"
|
|
||||||
},
|
|
||||||
"FluentValidation.DependencyInjectionExtensions": {
|
|
||||||
"target": "Package",
|
|
||||||
"version": "[11.9.1, )"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"imports": [
|
|
||||||
"net461",
|
|
||||||
"net462",
|
|
||||||
"net47",
|
|
||||||
"net471",
|
|
||||||
"net472",
|
|
||||||
"net48",
|
|
||||||
"net481"
|
|
||||||
],
|
|
||||||
"assetTargetFallback": true,
|
|
||||||
"warn": true,
|
|
||||||
"frameworkReferences": {
|
|
||||||
"Microsoft.NETCore.App": {
|
|
||||||
"privateAssets": "all"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.101/PortableRuntimeIdentifierGraph.json"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimes": {
|
|
||||||
"linux-x64": {
|
|
||||||
"#import": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\GreenHome.Domain.csproj": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"restore": {
|
|
||||||
"projectUniqueName": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\GreenHome.Domain.csproj",
|
|
||||||
"projectName": "GreenHome.Domain",
|
|
||||||
"projectPath": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\GreenHome.Domain.csproj",
|
|
||||||
"packagesPath": "C:\\Users\\Mohammad\\.nuget\\packages\\",
|
|
||||||
"outputPath": "D:\\Data\\Projects\\php\\greenhome\\src\\GreenHome.Domain\\obj\\",
|
|
||||||
"projectStyle": "PackageReference",
|
|
||||||
"fallbackFolders": [
|
|
||||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
|
||||||
],
|
|
||||||
"configFilePaths": [
|
|
||||||
"C:\\Users\\Mohammad\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
|
||||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
|
||||||
],
|
|
||||||
"originalTargetFrameworks": [
|
|
||||||
"net9.0"
|
|
||||||
],
|
|
||||||
"sources": {
|
|
||||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
|
||||||
"https://api.nuget.org/v3/index.json": {}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net9.0": {
|
|
||||||
"targetAlias": "net9.0",
|
|
||||||
"projectReferences": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"warningProperties": {
|
|
||||||
"warnAsError": [
|
|
||||||
"NU1605"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"restoreAuditProperties": {
|
|
||||||
"enableAudit": "true",
|
|
||||||
"auditLevel": "low",
|
|
||||||
"auditMode": "direct"
|
|
||||||
},
|
|
||||||
"SdkAnalysisLevel": "9.0.100"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net9.0": {
|
|
||||||
"targetAlias": "net9.0",
|
|
||||||
"imports": [
|
|
||||||
"net461",
|
|
||||||
"net462",
|
|
||||||
"net47",
|
|
||||||
"net471",
|
|
||||||
"net472",
|
|
||||||
"net48",
|
|
||||||
"net481"
|
|
||||||
],
|
|
||||||
"assetTargetFallback": true,
|
|
||||||
"warn": true,
|
|
||||||
"frameworkReferences": {
|
|
||||||
"Microsoft.NETCore.App": {
|
|
||||||
"privateAssets": "all"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.101/PortableRuntimeIdentifierGraph.json"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimes": {
|
|
||||||
"linux-x64": {
|
|
||||||
"#import": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
|
||||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
|
||||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
|
||||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
|
||||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
|
||||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Mohammad\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
|
||||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
|
||||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.12.2</NuGetToolVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
|
||||||
<SourceRoot Include="C:\Users\Mohammad\.nuget\packages\" />
|
|
||||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user