This code is branched off my working main repository which contains a much more complex dual SmartApp setup with a React client Front-End that integrates with another SmartApp that was removed from this branch. I attempted to branch this while the Rules SmartApp was still fairly isolated before I really move forward mixing it with the FrontEnd and other SmartApp in the main branch.
This code is a static long-running branch that has been pruned down to illustrate a working SmartApp that interfaces with the Rules API and creates a practical rule-set that I use for my needs.
This is targeted at hobbiest SmartApp developers who may be interested in a full-scale working application example. For developers just wandering into the Samsung SmartThings developer space it may come across as overly-complicated and you may find better resources at the SmartThings Community GitHub for introductary purposes. However, none of those apps really put things together in a real world use-case which is what this example intends to do.
These steps are intentionally different than may of the example SmartApp Community examples. I attempt to layout the explicit steps necessary to get a local development environment up and running. This example cannot be hosted on automated web hosting platforms like other SmartThings Community examples.
- Latest version of NodeJS installed on your computer (known to work with 18+)
-
Clone this app to a local directory
-
Download NGrok and set up a FREE account, then configure NGrok according to the basic setup instructions on the download page.
- This is required assuming your development environment does not have a public-facing internet address
- this service sets up a secure tunnel that is required for proper OAuth communication between Samsung Cloud, your SmartThings Hub and your locally running development web-server
- After installing and setting it up, you do not need to manually run it, the node scripts
tunnelruns ngrok internally
-
Create a file named
server/.env.localcontaining the following text
ENV_TYPE=dev|prod
STHOST=localhost # (empty for *)
STPORT=SETLOCALPORTNUMBER
API_TOKEN=SEENEXTSTEPPART2
CONTROL_APP_ID=SEENEXTSTEP
CONTROL_CLIENT_ID=SEENEXTSTEP
CONTROL_CLIENT_SECRET=SEENEXTSTEP
RULE_APP_ID=SEENEXTSTEP
RULE_CLIENT_ID=SEENEXTSTEP
RULE_CLIENT_SECRET=SEENEXTSTEP
LOCALIPS=192.168.1.1/24,127.0.0.1,::ffff:127.0.0.1,::1 # (your local nets)
LOGGING_EVENTS_ENABLED=false # or true
REDIS_SERVER=LOCALREDISPORT # TODO: document redis setup
Replace in
SETLOCALPORTNUMBERwith a local port of your choosing (suggest anything 5000-64000).
Replace
LOCALIPLISTwith a comma-separated list of IPV4, IPV6 and CIDR-Range addresses (i.e.192.168.1.0/28,127.0.0.1,::ffff:127.0.0.1,::1)
-
Setup The App In Samsung Developer Portal
- Setup a Samsung PWT (TODO: document this process)
-
Continue to the 'Everyday development instructions' below
Run all of these from the package.json located in the 'server' directory (cd server or point-click from VS code UI)
npm install && npm run inst(to install the top-level npm dependencies, then the dependencies of each subdir)npm run startfrom the top-level directories will start entire dev environment in a single console session (using concurrently)- alternatively, you can run individual parts of the
npm run startcommand above to control each part individually
- alternatively, you can run individual parts of the
- (Re)Verify The App In Samsung Developer Workspace
- You must do this every time you start/restart
npm run tunneltask which includes every time you run the mainnpm run startcommand
- You must do this every time you start/restart
Finally! You are ready to develop! Once you make changes, you need to stop and start ONLY the npm run server task
You do not want or need to restart the npm run tunnel task. If you do so, you will need to follow steps above to re-verify your App Registration with the new URL after NGrok restarts.
When you make changes to the server/smartapp, and restart you do not need to uninstall or re-install a working development app.
- Functional Samsung SmartApp Developed On Current Platform and API
- Implementation of new Rules API that creates rules directly from SmartApp configuration
- Allows multiple installs of the app, in this example allowing many simlar rulesets to be defined for different locations in a home/office
- Proper node express server, with middleware options (NOTE: No authorization configured SEE NOTE BELOW)
- Full TypeScript application, almost entirely accurate TS definitions used
- Configured to run with new, experimental ESM support coming standard in pending Node minor release
- Strict ESLint configuration and adherance (NOTE: should integrate ESLint into git commit hooks)
- Complete and Accurate (hopefully, I tried!) SmartThings setup documentation with images and code snippets
- Stable VSCode integration, ready for use with npm and eslint (and other) VSCode plugins
- Proper seperation of 'development' vs 'production' libraries for efficient and minimal runtime env
- Proper setup and use of 'dotenv' to safely store security data away from repository
- (Extra) Simple, but exemplified persistent storage (redis) linking web-app stored data to server stored data
- (Extra) SSE (server-side-events) available to also pipe communication between server and smartapp (not heavily leveraged in this example, but left in code)
- The node express website only protected by local ip detection This is not considered adequate protection by web security experts.
- Custom, personal SmartApps cannot be shared across users =(
- So, after all this work, and setting up many SmartApps to customize the rules in my home, I was disappointed to find out my wife could not see and control the SmartApps I had set up
- You are limited to 100 Rules/User and 50 Rules/ISA
- I have now made improvements to collapse rules down to only 2 max per app install, but you can still hit this limit with enough apps installed
- Very 'perscriptive' ESLint RuleSet
- I feel that the 'default' ESLint ruleset, while a good start, does not demand enough coding standards and consistent practices, so I leveraged a specific ruleset with which I am familiar that is a lot more explicit. Relax or tune this as you wish if you do not like the standards that are defined.
- run
npm run build(builds into/builddirectory) - check-in or otherwise copy that output to build server hosting directory
- be sure to configure the
.envfile on the server checkout directory npm --prodon server to install neccessary runtime libsnpm run prodto run the server environment (or put the code in the script in a .service file)
- Rule Helper Sample Project - this is the basis of this repository with some early commits cherry-picked from this repository. Full credit to him for some of the fundamental bits here!
- SmartThings Community (Forums) - to all those who take time to talk and support the community here
- SmartThings Community (GitHub) - example projects from Samsung public for the community! Many thanks and bits taken from the examples here
- SmartThings Community TypeScript Example - many TS hints scrounged from here
- SmartThings Community All Settings Example - useful example of settings options
- Rules API reference - rules API reference (and other docs)
I am essentially contributing this branch, as-is, to the community to extend, develop, use as a start, whatever. But...
I really don't intend to develop this branch much further or clean/refine it. I will attempt to back-port major bugs or vulnerabilities, but really this is just branched off at this point-in-time to be used as example code.
I MAY consider fork contributions if contacted or PR(s) if I end up having them configured. My hesitation is only with regards to my time, of which I don't have much to spare. I am not trying to discourage community participation.
I really intend to continue to build out the main branch of this repository according to my needs and that will also remain public for example(s) although it may become much more complicated.
- Why doesnt add imports map the proper file (or even always show node-modules available for client?)
- https://medium.com/geekculture/avoid-relative-path-hell-in-typescript-backend-41417b0086b7 seems good idea in its own PR
- Autoformatter settings figured out? may need to upgrade eslint and the rules?? (wip: 7c3506f upgrade typescript, separate PR)
- lint on checkin?
- advanced logging and log routings (categories, enable/disable in .env, verbose logging to specific file, some/all captured by syslog?)
- different icons for different light types (fan, fanlight, light, ??)
- show % of dim instead of on/off
- .env for client being baked into production build