initial commit
This commit is contained in:
Родитель
6eb724e086
Коммит
31c107e2b3
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"eslint-plugin-import",
|
||||
"eslint-plugin-jsdoc",
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"no-shadow": "off",
|
||||
"@typescript-eslint/no-shadow": "error",
|
||||
"no-unused-expressions": "off",
|
||||
"@typescript-eslint/no-unused-expressions": "error",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"no-unneeded-ternary": "error",
|
||||
"array-bracket-newline": [
|
||||
"error",
|
||||
"consistent"
|
||||
],
|
||||
"brace-style": [
|
||||
"error",
|
||||
"stroustrup"
|
||||
],
|
||||
"comma-dangle": "error",
|
||||
"eqeqeq": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"id-blacklist": [
|
||||
"error",
|
||||
"any",
|
||||
"Number",
|
||||
"number",
|
||||
"String",
|
||||
"string",
|
||||
"Boolean",
|
||||
"boolean",
|
||||
"Undefined",
|
||||
"undefined"
|
||||
],
|
||||
"max-classes-per-file": [
|
||||
"off",
|
||||
1
|
||||
],
|
||||
"max-len": [
|
||||
"error",
|
||||
{
|
||||
"code": 200
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"allowTemplateLiterals": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
"types": {
|
||||
"Object": {
|
||||
"message": "Avoid using the `Object` type. Did you mean `object`?"
|
||||
},
|
||||
"Function": {
|
||||
"message": "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."
|
||||
},
|
||||
"Boolean": {
|
||||
"message": "Avoid using the `Boolean` type. Did you mean `boolean`?"
|
||||
},
|
||||
"Number": {
|
||||
"message": "Avoid using the `Number` type. Did you mean `number`?"
|
||||
},
|
||||
"String": {
|
||||
"message": "Avoid using the `String` type. Did you mean `string`?"
|
||||
},
|
||||
"Symbol": {
|
||||
"message": "Avoid using the `Symbol` type. Did you mean `symbol`?"
|
||||
},
|
||||
"{}": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"indent": "off",
|
||||
"@typescript-eslint/indent": "error",
|
||||
"@typescript-eslint/member-delimiter-style": "error",
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
"@typescript-eslint/no-explicit-any": [
|
||||
"off",
|
||||
{
|
||||
"ignoreRestArgs": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/array-type": [
|
||||
"error",
|
||||
{
|
||||
"default": "array"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/consistent-type-assertions": "error",
|
||||
"@typescript-eslint/consistent-type-definitions": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": [
|
||||
"error",
|
||||
{
|
||||
"accessibility": "explicit",
|
||||
"overrides": {
|
||||
"constructors": "no-public"
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/member-ordering": "off",
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"error",
|
||||
{
|
||||
"selector": [
|
||||
"enumMember",
|
||||
"enum"
|
||||
],
|
||||
"format": null
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-empty-function": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-this-alias": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "error",
|
||||
"@typescript-eslint/prefer-function-type": "error",
|
||||
"@typescript-eslint/prefer-namespace-keyword": "error",
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unified-signatures": "error",
|
||||
"@typescript-eslint/explicit-module-boundary-types": [
|
||||
"error",
|
||||
{
|
||||
"allowArgumentsExplicitlyTypedAsAny": true
|
||||
}
|
||||
],
|
||||
"object-shorthand": "error",
|
||||
"arrow-parens": [
|
||||
"off",
|
||||
"always"
|
||||
],
|
||||
"constructor-super": "error",
|
||||
"curly": "error",
|
||||
"eol-last": "error",
|
||||
"guard-for-in": "error",
|
||||
"import/no-extraneous-dependencies": "error",
|
||||
"import/no-internal-modules": "error",
|
||||
"import/order": "off",
|
||||
"jsdoc/check-alignment": "error",
|
||||
"jsdoc/check-indentation": "error",
|
||||
"jsdoc/newline-after-description": "error",
|
||||
"new-parens": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-caller": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-console": "error",
|
||||
"no-debugger": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-empty": "error",
|
||||
"no-eval": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-fallthrough": "off",
|
||||
"no-invalid-this": "off",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-multiple-empty-lines": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-return-await": "error",
|
||||
"no-sequences": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-underscore-dangle": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"no-var": "error",
|
||||
"one-var": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"prefer-const": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"prefer-template": "error",
|
||||
"quote-props": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
"radix": "error",
|
||||
"space-before-function-paren": [
|
||||
"error",
|
||||
{
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}
|
||||
],
|
||||
"spaced-comment": [
|
||||
"error",
|
||||
"always"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,350 +1,84 @@
|
|||
## 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/master/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/
|
||||
[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 of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# 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
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build
|
||||
build/Release
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# 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
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
# TSD Typings
|
||||
typings/
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
# npm related
|
||||
.npm
|
||||
.npmrc*
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
# Build output
|
||||
dist
|
||||
server_dist
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
# Ignore Mac DS_Store files
|
||||
.DS_Store
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
debug.json
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
*.swp
|
||||
**/bundle-*.js
|
||||
**/bundle-*.js.map
|
||||
**/common.js
|
||||
**/common.js.map
|
||||
coverage.html
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
# node profiler
|
||||
profile**.txt
|
||||
|
||||
# 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/
|
||||
# project
|
||||
client
|
||||
configs/**
|
||||
storage*/**
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible Node.js debug attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "IoT Central File Upload Device",
|
||||
"console": "integratedTerminal",
|
||||
"program": "${workspaceFolder}/index.ts",
|
||||
"protocol": "inspector",
|
||||
"smartStep": true,
|
||||
"showAsyncStacks": true,
|
||||
"sourceMaps": true,
|
||||
"preLaunchTask": "ts-watch",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "typescript",
|
||||
"label": "build",
|
||||
"tsconfig": "tsconfig.json",
|
||||
"group": "build",
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "typescript",
|
||||
"label": "ts-watch",
|
||||
"isBackground": true,
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"panel": "new",
|
||||
"reveal": "never"
|
||||
},
|
||||
"tsconfig": "tsconfig.json",
|
||||
"option": "watch",
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "eslint",
|
||||
"problemMatcher": [
|
||||
"$eslint-stylish"
|
||||
],
|
||||
"label": "npm: lint",
|
||||
"detail": "eslint -c .eslintrc.json --ext .ts ."
|
||||
}
|
||||
]
|
||||
}
|
123
README.md
123
README.md
|
@ -1,57 +1,96 @@
|
|||
# Project Name
|
||||
---
|
||||
page_type: sample
|
||||
name: "IoT Central file upload device sample"
|
||||
description: "Sample code that demonstrates how a device can use IoT Central to upload a file to cloud storage."
|
||||
languages:
|
||||
- typescript
|
||||
products:
|
||||
- azure-iot-central
|
||||
urlFragment: iotc-file-upload-device
|
||||
---
|
||||
|
||||
(short, 1-3 sentenced, description of the project)
|
||||
# IoT Central file upload device sample
|
||||
This sample demonstrates how to use the file upload feature of IoT Hub from within an IoT Central app. For a full description of the IoT Central File Upload feature see the [documentation online](https://apps.azureiotcentral.com).
|
||||
|
||||
## Features
|
||||
## Prerequisites
|
||||
* [Node.js](https://nodejs.org/en/download/)
|
||||
* [Visual Studio Code](https://code.visualstudio.com/Download) with [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extension installed, or a command line will work.
|
||||
* [Azure Blob Storage account](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-portal)
|
||||
* [IoT Central Application](https://docs.microsoft.com/en-us/azure/iot-central/core/quick-deploy-iot-central)
|
||||
|
||||
This project framework provides the following features:
|
||||
## Clone the repository
|
||||
If you haven't already cloned the repository, use the following command to clone it to a suitable location on your local machine and install the dependent packages:
|
||||
```
|
||||
git clone https://github.com/iot-for-all/iotc-file-upload-device
|
||||
cd iotc-file-upload-device
|
||||
npm i
|
||||
```
|
||||
Open the cloned repository with VS Code.
|
||||
|
||||
* Feature 1
|
||||
* Feature 2
|
||||
* ...
|
||||
## Create an IoT Central application
|
||||
Follow the instructions to [create an IoT Central application](https://docs.microsoft.com/en-us/azure/iot-central/core/quick-deploy-iot-central) and associate the application with your Azure Storage account. Create a new device template using the included file upload device sample template.
|
||||
* From the left pane in your IoT Central Application select "Device templtes"
|
||||
* At the top of the device templates view select the "+ New" option to create a new template
|
||||
* Select the "IoT Device" option
|
||||
* Select the "Next: Customize" button
|
||||
* Name your template (e.g. File Upload Device Sample)
|
||||
* Select the "Next: Review" button
|
||||
* Select the "Create" button
|
||||
* Select the "Import capability model" option. The device template is included in the project here */setup/FileUploadDeviceDcm.json*.
|
||||
|
||||
## Getting Started
|
||||
After importing the device template you need to create a view on the telemetry and properties the device will send and receive. See the documentation to [Create and manage dashboards in IoT Central](https://docs.microsoft.com/en-us/azure/iot-central/core/howto-create-personal-dashboards). Create a dashboard view for *Visualizing the device*
|
||||
* In your new device template select the "Views" option
|
||||
* Select the "Visualize the device" option
|
||||
* For the "View name" enter "Dashboard"
|
||||
* Select the `System Heartbeat` telemetry and then the "Add tile" button at the bottom. This telemetry is a heartbeat signal that shows that your device is alive and running. This signal will be charted on a graph.
|
||||
* Select the `Upload Image` telemtry and then the "Add tile" button at the bottom. This telemetry is an event that will indicated when a file upload has occurred.
|
||||
* Select the "Save" option for this view.
|
||||
|
||||
### Prerequisites
|
||||
Create another view for *Editing device and cloud data*
|
||||
* Select the "Views" option
|
||||
* Select the "Editing device and cloud data" option
|
||||
* For the "Form name" enter "Upload options"
|
||||
* Select the `Filename Suffix` property and then the "Add section" button at the bottom. This property is the suffix to use on the uploaded file name.
|
||||
* Select the "Save" option for this view.
|
||||
|
||||
(ideally very short, if any)
|
||||
Now publish the template by selecting the "Publish" option at the top of the screen. You are now ready to create a device and run the sample code.
|
||||
|
||||
- OS
|
||||
- Library version
|
||||
- ...
|
||||
## Create an IoT Device
|
||||
In your IoT Central application create a new device based on your new template and get the connection information.
|
||||
* From the left pane in your IoT Central Application select "Devices"
|
||||
* In the device list view select the "+ New" option
|
||||
* In the Create a new device screen specify your template, a Device name, and a Device ID
|
||||
* Select the "Create" button
|
||||
* In the device list select your new device
|
||||
* In the device view select the "Connect" option at the top of the screen
|
||||
* Copy the values for "ID scope", "Device ID", and "Primary key". You will use these values in the device sample code.
|
||||
|
||||
### Installation
|
||||
To learn more, see [Add a device in IoT Central application.](https://docs.microsoft.com/en-us/azure/iot-central/core/howto-manage-devices#add-a-device)
|
||||
|
||||
(ideally very short)
|
||||
## Run the sample code
|
||||
Create a ".env" file at the root of your project and add the values you copied above. The file should look like the sample below with your own values. NOTE: the modelId is copied from the */setup/FileUploadDeviceDcm.json* file.
|
||||
```
|
||||
scopeId=<YOUR_SCOPE_ID>
|
||||
deviceId=<YOUR_DEVICE_ID>
|
||||
deviceKey=<YOUR_PRIMARY_KEY>
|
||||
modelId=dtmi:IoTCentral:IotCentralFileUploadDevice;1
|
||||
```
|
||||
|
||||
- npm install [package name]
|
||||
- mvn install
|
||||
- ...
|
||||
Now you are ready to run the sample. Press F5 to run/debug the sample. In your terminal window you should see that the device is registered and is connected to IoT Central:
|
||||
```
|
||||
Starting IoT Central device...
|
||||
> Machine: ...
|
||||
Starting device registration...
|
||||
DPS registration succeeded
|
||||
Connecting the device...
|
||||
IoT Central successfully connected device: file-upload-device
|
||||
```
|
||||
|
||||
### Quickstart
|
||||
(Add steps to get up and running quickly)
|
||||
## Upload a file
|
||||
The sample project comes with a sample file named datafile.json. This will be the file that is uploaded when you use the Upload File command in your IoT Central application. To test this open your application and select the device you created. Select the Command tab and you should see a button named "Run". When you select that button the IoT Central app will call a direct method on your device to upload the file. You can see this direct method in the sample code in the */device.ts* file. The method is named *uploadFileCommand*.
|
||||
|
||||
1. git clone [repository clone url]
|
||||
2. cd [respository name]
|
||||
3. ...
|
||||
The *uploadFileCommand* calls a method named *uploadFile*. This method gets the device setting for the filename suffix to use. By default the built-in file upload feature automatically creates a folder with the same name as your deviceId. This device setting is purely to demonstrate how to communicate property changes to your device from IoT Central. After getting the file name and some information about file to upload the code calls the built-in IoT Hub method `deviceClient.uploadToBlob` on the device client interface. This uses the IoT Hub file upload feature to stream the file to the associated Azure Blob storage.
|
||||
|
||||
> While this sample uses the Command capability in IoT Central to call a direct method on your device in order to upload a file it it not required. For example you could have a video analytics device that automatically uploads a sample image when it detects an anomaly.
|
||||
|
||||
## Demo
|
||||
|
||||
A demo app is included to show how to use the project.
|
||||
|
||||
To run the demo, follow these steps:
|
||||
|
||||
(Add steps to start up the demo)
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Resources
|
||||
|
||||
(Any additional resources or related projects)
|
||||
|
||||
- Link to supporting information
|
||||
- Link to similar sample
|
||||
- ...
|
||||
This sample demonstrates the simplest way to upload generic files to an Azure Blob Storage account. The features of the IoT Hub take care of creating the SAS token for the connection. If you need more fine grained control of the features of Azure Blob Storage from your IoT Device then you will need to use the Azure Storage SDK directly in your Azure IoT Device project. To learn more about the Azure Blob Storage SDK see the [Azure Blob storage documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction).
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"test": "field1"
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
import { Mqtt } from 'azure-iot-device-mqtt';
|
||||
import { SymmetricKeySecurityClient } from 'azure-iot-security-symmetric-key';
|
||||
import { ProvisioningDeviceClient } from 'azure-iot-provisioning-device';
|
||||
import { Mqtt as ProvisioningTransport } from 'azure-iot-provisioning-device-mqtt';
|
||||
import {
|
||||
Client as IoTDeviceClient,
|
||||
Twin,
|
||||
Message as IoTMessage,
|
||||
DeviceMethodRequest,
|
||||
DeviceMethodResponse
|
||||
} from 'azure-iot-device';
|
||||
import {
|
||||
extname as pathExtName,
|
||||
basename as pathBaseName
|
||||
} from 'path';
|
||||
import {
|
||||
stat as fsStat,
|
||||
createReadStream as fsCreateReadStream
|
||||
} from 'fs';
|
||||
import * as moment from 'moment';
|
||||
import { log } from 'util';
|
||||
|
||||
const dpsProvisioningHost = 'global.azure-devices-provisioning.net';
|
||||
|
||||
const CommandUploadFile = 'COMMAND_UPLOAD_FILE';
|
||||
const TelemetrySystemHeartbeat = 'TELEMETRY_SYSTEM_HEARTBEAT';
|
||||
const EventUploadFile = 'EVENT_UPLOAD_FILE';
|
||||
const SettingFilenameSuffix = 'SETTING_FILENAME_SUFFIX';
|
||||
const CommandResponseStatusCode = 'COMMANDRESPONSE_STATUSCODE';
|
||||
const CommandResponseMessage = 'COMMANDRESPONSE_MESSAGE';
|
||||
const CommandResponseData = 'COMMANDRESPONSE_DATA';
|
||||
|
||||
interface IFileUploadResponse {
|
||||
statusCode: number;
|
||||
message: string;
|
||||
filename: string;
|
||||
}
|
||||
|
||||
interface IDeviceSettings {
|
||||
[SettingFilenameSuffix]: string;
|
||||
}
|
||||
|
||||
export class IoTCentralDevice {
|
||||
private log: (message: string) => void;
|
||||
private scopeId: string;
|
||||
private deviceId: string;
|
||||
private deviceKey: string;
|
||||
private modelId: string;
|
||||
|
||||
private deviceClient: IoTDeviceClient;
|
||||
private deviceTwin: Twin;
|
||||
private deviceSettings: IDeviceSettings;
|
||||
|
||||
constructor(logFunc: (message: string) => void, scopeId: string, deviceId: string, deviceKey: string, modelId: string) {
|
||||
this.log = logFunc;
|
||||
this.scopeId = scopeId;
|
||||
this.deviceId = deviceId;
|
||||
this.deviceKey = deviceKey;
|
||||
this.modelId = modelId;
|
||||
|
||||
this.deviceSettings = {
|
||||
[SettingFilenameSuffix]: moment.utc().format('YYYYMMDD-HHmmss')
|
||||
};
|
||||
}
|
||||
|
||||
public async provisionDeviceClient(): Promise<string> {
|
||||
let connectionString = '';
|
||||
|
||||
try {
|
||||
const provisioningSecurityClient = new SymmetricKeySecurityClient(this.deviceId, this.deviceKey);
|
||||
const provisioningClient = ProvisioningDeviceClient.create(
|
||||
dpsProvisioningHost,
|
||||
this.scopeId,
|
||||
new ProvisioningTransport(),
|
||||
provisioningSecurityClient
|
||||
);
|
||||
|
||||
const provisioningPayload = {
|
||||
iotcModelId: this.modelId
|
||||
};
|
||||
|
||||
provisioningClient.setProvisioningPayload(provisioningPayload);
|
||||
|
||||
connectionString = await new Promise<string>((resolve, reject) => {
|
||||
provisioningClient.register((dpsError, dpsResult) => {
|
||||
if (dpsError) {
|
||||
return reject(dpsError);
|
||||
}
|
||||
|
||||
this.log('DPS registration succeeded');
|
||||
|
||||
return resolve(`HostName=${dpsResult.assignedHub};DeviceId=${dpsResult.deviceId};SharedAccessKey=${this.deviceKey}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
this.log(`Failed to instantiate client interface from configuration: ${ex.message}`);
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
public async connectDeviceClient(connectionString: string): Promise<void> {
|
||||
try {
|
||||
this.deviceClient = await IoTDeviceClient.fromConnectionString(connectionString, Mqtt);
|
||||
if (!this.deviceClient) {
|
||||
this.log(`Failed to connect device client interface from connection string - device: ${this.deviceId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
setInterval(async () => {
|
||||
await this.getHealth();
|
||||
}, 1000 * 30);
|
||||
|
||||
await this.deviceClient.open();
|
||||
|
||||
this.deviceTwin = await this.deviceClient.getTwin();
|
||||
this.deviceTwin.on('properties.desired', this.onHandleDeviceProperties.bind(this));
|
||||
|
||||
this.deviceClient.on('error', this.onDeviceClientError.bind(this));
|
||||
|
||||
this.deviceClient.onDeviceMethod(CommandUploadFile, this.uploadFileCommand.bind(this));
|
||||
|
||||
this.log(`IoT Central successfully connected device: ${this.deviceId}`);
|
||||
}
|
||||
catch (ex) {
|
||||
this.log(`IoT Central connection error: ${ex.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async getHealth(): Promise<void> {
|
||||
await this.sendMeasurement({
|
||||
[TelemetrySystemHeartbeat]: 1
|
||||
});
|
||||
}
|
||||
|
||||
private async onHandleDeviceProperties(desiredChangedSettings: any) {
|
||||
try {
|
||||
const patchedProperties = {};
|
||||
|
||||
for (const setting in desiredChangedSettings) {
|
||||
if (!Object.prototype.hasOwnProperty.call(desiredChangedSettings, setting)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setting === '$version') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = desiredChangedSettings[setting];
|
||||
|
||||
switch (setting) {
|
||||
case SettingFilenameSuffix:
|
||||
this.log(`Updating setting: ${setting} with value: ${value}`);
|
||||
|
||||
// NOTE: validation should be in place for legal folder names
|
||||
patchedProperties[setting] = this.deviceSettings[setting] = value || moment.utc().format('YYYYMMDD-HHmmss');
|
||||
break;
|
||||
|
||||
default:
|
||||
this.log(`Received desired property change for unknown setting '${setting}'`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(patchedProperties).length) {
|
||||
await this.updateDeviceProperties(patchedProperties);
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
this.log(`Exception while handling desired properties: ${ex.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private onDeviceClientError(error: Error) {
|
||||
this.log(`Device client connection error: ${error.message}`);
|
||||
}
|
||||
|
||||
private async sendMeasurement(data: any): Promise<void> {
|
||||
if (!data || !this.deviceClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.log(`Sending telemetry: ${JSON.stringify(data, null, 4)}`);
|
||||
|
||||
const iotcMessage = new IoTMessage(JSON.stringify(data));
|
||||
|
||||
await this.deviceClient.sendEvent(iotcMessage);
|
||||
}
|
||||
catch (ex) {
|
||||
this.log(`sendMeasurement: ${ex.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async updateDeviceProperties(properties: any): Promise<void> {
|
||||
if (!properties || !this.deviceTwin) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log(`Updating twin properties: ${JSON.stringify(properties, null, 4)}`);
|
||||
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
this.deviceTwin.properties.reported.update(properties, (error) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
return resolve('');
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
this.log(`Error updating device properties: ${ex.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async getFileStats(filePath: string): Promise<any> {
|
||||
let fileStats = {};
|
||||
|
||||
try {
|
||||
fileStats = await new Promise((resolve, reject) => {
|
||||
fsStat(filePath, (err, stats) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
return resolve(stats);
|
||||
});
|
||||
});
|
||||
}
|
||||
catch (ex) {
|
||||
log(`An error occurred while getting file stats: ${ex.message}`);
|
||||
}
|
||||
|
||||
return fileStats;
|
||||
}
|
||||
|
||||
private async uploadFile(filePath: string): Promise<IFileUploadResponse> {
|
||||
const result: IFileUploadResponse = {
|
||||
statusCode: 202,
|
||||
message: '',
|
||||
filename: ''
|
||||
};
|
||||
|
||||
try {
|
||||
const blobNameSuffix = this.deviceSettings[SettingFilenameSuffix];
|
||||
const fileExtName = pathExtName(filePath);
|
||||
const fileBaseName = pathBaseName(filePath, fileExtName);
|
||||
const fileStats = await this.getFileStats(filePath);
|
||||
const blobFilename = `${fileBaseName}-${blobNameSuffix}${fileExtName}`;
|
||||
const readableStream = fsCreateReadStream(filePath);
|
||||
|
||||
this.log(`uploadContent - data length: ${fileStats.size}, blob filename: ${blobFilename}`);
|
||||
|
||||
await this.deviceClient.uploadToBlob(blobFilename, readableStream, fileStats.size);
|
||||
|
||||
await this.sendMeasurement({
|
||||
[EventUploadFile]: `${blobFilename}`
|
||||
});
|
||||
|
||||
result.message = `deviceId: '${this.deviceId}' uploaded a file named '${blobFilename}' to the Azure storage container`;
|
||||
this.log(result.message);
|
||||
|
||||
result.filename = blobFilename;
|
||||
}
|
||||
catch (ex) {
|
||||
result.message = `Error during deviceClient.uploadToBlob: ${ex.message}`;
|
||||
this.log(result.message);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// @ts-ignore (commandRequest)
|
||||
private async uploadFileCommand(commandRequest: DeviceMethodRequest, commandResponse: DeviceMethodResponse) {
|
||||
this.log('Received upload file command');
|
||||
|
||||
const fileUploadResult = await this.uploadFile('./datafile.json');
|
||||
|
||||
await commandResponse.send(200);
|
||||
await this.updateDeviceProperties({
|
||||
[CommandUploadFile]: {
|
||||
value: {
|
||||
[CommandResponseStatusCode]: 202,
|
||||
[CommandResponseMessage]: fileUploadResult.message,
|
||||
[CommandResponseData]: ''
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import { resolve } from 'path';
|
||||
import { config } from 'dotenv';
|
||||
|
||||
config({ path: resolve(__dirname, '../.env') });
|
|
@ -0,0 +1,53 @@
|
|||
import './env';
|
||||
import {
|
||||
type as osType,
|
||||
cpus as osCpus,
|
||||
freemem as osFreeMem,
|
||||
totalmem as osTotalMem
|
||||
} from 'os';
|
||||
import { IoTCentralDevice } from './device';
|
||||
|
||||
function log(message: string) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(message);
|
||||
}
|
||||
|
||||
async function start() {
|
||||
try {
|
||||
log('🚀 Starting IoT Central device...');
|
||||
log(` > Machine: ${osType()}, ${osCpus().length} core, `
|
||||
+ `freemem=${(osFreeMem() / 1024 / 1024).toFixed(0)}mb, totalmem=${(osTotalMem() / 1024 / 1024).toFixed(0)}mb`);
|
||||
|
||||
const {
|
||||
scopeId,
|
||||
deviceId,
|
||||
deviceKey,
|
||||
modelId
|
||||
} = process.env;
|
||||
|
||||
if (!scopeId || !deviceId || !deviceKey || !modelId) {
|
||||
log('Error - missing required environment variables scopeId, deviceId, deviceKey, modelId');
|
||||
return;
|
||||
}
|
||||
|
||||
const iotDevice = new IoTCentralDevice(log, scopeId, deviceId, deviceKey, modelId);
|
||||
|
||||
log('Starting device registration...');
|
||||
const connectionString = await iotDevice.provisionDeviceClient();
|
||||
|
||||
if (connectionString) {
|
||||
log('Connecting the device...');
|
||||
await iotDevice.connectDeviceClient(connectionString);
|
||||
}
|
||||
else {
|
||||
log(' Failed to obtain connection string for device.');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
log(`👹 Error starting process: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
void (async () => {
|
||||
await start();
|
||||
})().catch();
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "iotc-file-upload-device",
|
||||
"version": "1.0.1",
|
||||
"description": "IoT Central File Upload Device Sample",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"eslint": "eslint -c .eslintrc.json --ext .ts .",
|
||||
"build": "node ./node_modules/typescript/bin/tsc -p ."
|
||||
},
|
||||
"author": "sseiber",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:sseiber/iotc-file-upload-device.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"azure-iot-device": "1.17.3",
|
||||
"azure-iot-device-mqtt": "1.15.3",
|
||||
"azure-iot-provisioning-device": "^1.8.7",
|
||||
"azure-iot-provisioning-device-mqtt": "^1.7.7",
|
||||
"azure-iot-security-symmetric-key": "^1.7.7",
|
||||
"dotenv": "^8.2.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.set": "^4.3.2",
|
||||
"moment": "^2.29.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.27",
|
||||
"@typescript-eslint/eslint-plugin": "^4.12.0",
|
||||
"@typescript-eslint/parser": "^4.12.0",
|
||||
"eslint": "^7.17.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsdoc": "^31.6.1",
|
||||
"typescript": "^4.1.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
"@id": "dtmi:IoTCentral:IotCentralFileUploadDevice;1",
|
||||
"@type": "Interface",
|
||||
"contents": [
|
||||
{
|
||||
"@id": "dtmi:IoTCentral:IotCentralFileUploadDevice:systemHeartBeat;1",
|
||||
"@type": "Telemetry",
|
||||
"displayName": {
|
||||
"en": "System Heartbeat"
|
||||
},
|
||||
"name": "TELEMETRY_SYSTEM_HEARTBEAT",
|
||||
"schema": "integer"
|
||||
},
|
||||
{
|
||||
"@id": "dtmi:IoTCentral:IotCentralFileUploadDevice:eventUploadFile;1",
|
||||
"@type": [
|
||||
"Telemetry",
|
||||
"SemanticType/Event"
|
||||
],
|
||||
"displayName": {
|
||||
"en": "Upload Image"
|
||||
},
|
||||
"name": "EVENT_UPLOAD_FILE",
|
||||
"schema": "string"
|
||||
},
|
||||
{
|
||||
"@id": "dtmi:IoTCentral:IotCentralFileUploadDevice:settingFilenameSuffix;1",
|
||||
"@type": "Property",
|
||||
"displayName": {
|
||||
"en": "Filename Suffix"
|
||||
},
|
||||
"name": "SETTING_FILENAME_SUFFIX",
|
||||
"writable": true,
|
||||
"schema": "string"
|
||||
},
|
||||
{
|
||||
"@id": "dtmi:IoTCentral:IotCentralFileUploadDevice:command;1",
|
||||
"@type": "Command",
|
||||
"displayName": {
|
||||
"en": "Upload File"
|
||||
},
|
||||
"name": "COMMAND_UPLOAD_FILE",
|
||||
"response": {
|
||||
"@type": "SchemaField",
|
||||
"displayName": {
|
||||
"en": "Command Response"
|
||||
},
|
||||
"name": "CommandResponse",
|
||||
"schema": "dtmi:IoTCentral:IotCentralFileUploadDevice:command:responseSchema;1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"schemas": [
|
||||
{
|
||||
"@id": "dtmi:IoTCentral:IotCentralFileUploadDevice:command:responseSchema;1",
|
||||
"@type": "Object",
|
||||
"displayName": {
|
||||
"en": "Object"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"@type": "SchemaField",
|
||||
"displayName": {
|
||||
"en": "Status Code"
|
||||
},
|
||||
"name": "COMMANDRESPONSE_STATUSCODE",
|
||||
"schema": "long"
|
||||
},
|
||||
{
|
||||
"@type": "SchemaField",
|
||||
"displayName": {
|
||||
"en": "Message"
|
||||
},
|
||||
"name": "COMMANDRESPONSE_MESSAGE",
|
||||
"schema": "string"
|
||||
},
|
||||
{
|
||||
"@type": "SchemaField",
|
||||
"displayName": {
|
||||
"en": "Data"
|
||||
},
|
||||
"name": "COMMANDRESPONSE_DATA",
|
||||
"schema": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"displayName": {
|
||||
"en": "IoT Central File Upload Device"
|
||||
},
|
||||
"@context": [
|
||||
"dtmi:iotcentral:context;2",
|
||||
"dtmi:dtdl:context;2"
|
||||
]
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.7 KiB |
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"target": "ES6",
|
||||
"sourceMap": true,
|
||||
"jsx": "react",
|
||||
"skipLibCheck": true,
|
||||
"noImplicitAny": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
"lib": [
|
||||
"ES6"
|
||||
]
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"include": [
|
||||
"*.ts"
|
||||
]
|
||||
}
|
Загрузка…
Ссылка в новой задаче