The Simple IoT source code is available on Github.
Simple IoT is written in Go. Go package documentation is available.
Requirements:
- Go
- Node/NPM
Simple IoT build has currently been testing on Linux and MacOS systems. See
envsetup.sh
for scripts used in building.
To build:
source envsetup.sh
siot_setup
siot_build
npm install -g run-pty
. envsetup.sh
siot_setup
siot_watch
The siot_watch
command can be used when developing Simple IoT. This does the
following:
- starts
elm-watch
on the Elm code.elm-watch
will automatically update the UI without losing state any time an Elm file changes. - runs the Go backend and rebuilds it anytime a Go module changes (only tested on Linux and MacOS, but should be easy to set up Windows as well)
Both of the above are run in a run-pty
wrapper, which allows you to see the output of either process. The output of the
Elm compile is displayed in the browser, so it is rarely necessary to view the
elm-watch
side.
Simple IoT can be used a library for your custom application. The siot main.go illustrates how to start the SIOT server, and add clients. You can do this from any Go application. With a few lines of code, this gives you a lot of functionality including a NATS server.
Most SIOT functionality is implemented in clients. See the client documentation for more information.
Currently, there is no simple way to customize the SIOT UI when using SIOT as a library package. Forking and changing the SIOT Elm code is probably the simplest way if you want to make a small change now.
In the future, we plan to provide an API for passing in a custom UI to the SIOT Server. You can also implement a custom http client that serves up a custom UI.
Currently, there are a lot of subdirectories. One reason for this is to limit
the size of application binaries when building edge/embedded Linux binaries. In
some use cases, we want to deploy app updates over cellular networks, therefore
we want to keep packages as small as possible. For instance, if we put the
natsserver
stuff in the nats
package, then app binaries grow a couple MB,
even if you don't start a NATS server. It is not clear yet what Go does for dead
code elimination, but at this point, it seems referencing a package increases
the binary size, even if you don't use anything in it. (Clarification welcome!)
For edge applications on Embedded Linux, we'd eventually like to get rid of net/http, since we can do all network communications over NATS. We're not there yet, but be careful about pulling in dependencies that require net/http into the NATS package, and other low level packages intended for use on devices.
See Go docs directory descriptions
Please run siot_test
from envsetup.sh
before submitting pull requests. All
code should be formatted and linted before committing.
Please configure your editor to run code formatters:
- Go:
goimports
- Elm:
elm-format
- Markdown:
prettier
(note, there is a.prettierrc
in this project that configures prettier to wrap markdown to 80 characters. Whether to wrap markdown or not is debatable, as wrapping can make diffs harder to read, but Markdown is much more pleasant to read in an editor if it is wrapped. Since more people will be reading documentation than reviewing, lets optimize for the reading in all scenarios -- editor, Github, and generated docs)
We plan to keep the main Simple IoT application a pure Go binary if possible. Statically linked pure Go has huge advantages:
- you can easily cross compile to any target from any build machine.
- blazing fast compile times
- deployment is dead simple – zero dependencies. Docker is not needed.
- you are not vulnerable to security issues in the host systems SSL/TLS libs. What you deploy is pretty much what you get.
- although there is high quality code written in C/C++, it is much easier to write safe, reliable programs in Go, so I think long term there is much less risk using a Go implementation of about anything – especially if it is widely used.
- Go’s network programming model is much simpler than about anything else. Simplicity == less bugs.
Once you link to C libs in your Go program, you forgo many of the benefits of Go. The Go authors made a brilliant choice when they chose to build Go from the ground up. Yes, you loose the ability to easily use some of the popular C libraries, but what you gain is many times more valuable.
There are not a lot of unit tests in the project yet, but below are some examples of running tests:
- test everything:
go test -race ./...
- test only client directory:
go test -race ./client
- run only a specific: `go test -race ./client -run BackoffTest (run takes a RegEx)
siot_test
runs tests as well as vet/lint, frontend tests, etc.
The leading ./
is important, otherwise Go things you are giving it a package
name, not a directory. The ...
tells Go to recursively test all subdirs.
It is much more pleasant to write documentation and tests as you develop, rather than after the fact. These efforts add value to your development if done concurrently. Quality needs to be designed-in, and leading with documentation will result in better thinking and a better product.
If you develop a feature, please update/create any needed documentation and write any tests (especially end-to-end) to verify the feature works and continues to work.