Justifications and removing debug code.
parent
c0255bae0c
commit
d4b7a5c493
42
README.md
42
README.md
|
@ -1,6 +1,32 @@
|
|||
## Shingle
|
||||
|
||||
Stream-based home automation.
|
||||
Add reactive programming to your existing home automation toolkit.
|
||||
|
||||
## What
|
||||
|
||||
Attach to Home Assistant, MQTT, or another event source and write automations in normal Scala 3 using a normal text editor.
|
||||
|
||||
## Why?
|
||||
|
||||
Shingle was born out of frustration with the limited programming interfaces available on most popular frameworks.
|
||||
|
||||
* **Home Assistant** programming is done through YAML files or a GUI that mimics the YAML files, and a custom templating language. This is perfectly fine for simple if-this-then-that type tasks, but makes specifying complex conditions (e.g., "when either of two sensors changes, but debounce the signal") incredibly painful. The custom templating language is also rather frustrating.
|
||||
|
||||
* **MQTT** offers no programming framework. It's just a message bus, although admittedly an incredibly powerful one with extensive support across a multitude of languages.
|
||||
|
||||
* **Node.red** is conceptually very nice, offering a stream-based solution not unlike Shingle. However, it's also painful to get running and is based on the "move fast and break things" javascript ecosystem.
|
||||
|
||||
Shingle is designed to add sensible programming support to existing home automation buses like Home Assistant or MQTT.
|
||||
|
||||
* Shingle doesn't try to invent its own programming language. Write code in simple Scala 3.
|
||||
* Shingle doesn't try to be a message bus. Shingle plugs into MQTT or Home Assistant.
|
||||
* Shingle doesn't force you to use a crappy web-based editor. Use your existing code editor to write scripts, and Shingle will load them.
|
||||
|
||||
So what exactly does shingle provide:
|
||||
* Library code for reactive (stream-based) programming.
|
||||
* Library code for connecting to existing event buses (Home Assistant, MQTT) and entities (Hermes, MPD, REST endpoints).
|
||||
* A 'loader' that lets you dynamically load, enable, and disable individual pipelines.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
@ -19,8 +45,8 @@ Create a folder `~/.shingle` and a file `~/.shingle/config.json`:
|
|||
#### Example Script
|
||||
Create a folder `~/.shingle/scripts/` and a file `~/.shingle/scripts/Test.scala`
|
||||
```
|
||||
TimeEvents.every(3.seconds)
|
||||
.trigger { _ => println("Hi!") }
|
||||
Timer.every(3.seconds)
|
||||
.trigger { _ => println("Hi!") }
|
||||
```
|
||||
|
||||
#### Run Shingle
|
||||
|
@ -126,6 +152,16 @@ The [music player daemon](https://www.musicpd.org/). To use the MPD integration
|
|||
* `MPD.savedPlaylist(name)`: List all songs in the specified saved playlist
|
||||
* `MPD.append(path)`: Add the song at the specified path to the end of the playlist
|
||||
|
||||
## The Admin interface
|
||||
|
||||
More coming here eventually, but Shingle exposes a simple web interface for runtime management.
|
||||
|
||||
* `http://localhost:4000/api/modules`: List every available module (the contents of `~/.shingle/scripts` without the `.scala` extension).
|
||||
* `http://localhost:4000/api/modules/[script]`: Show the contents of the specified script.
|
||||
* `http://localhost:4000/api/modules/[script]/unload`: Disable all triggers created by the specified script.
|
||||
* `http://localhost:4000/api/modules/[script]/load`: Disable all triggers created by the specified script and reload it.
|
||||
|
||||
|
||||
## Compiling Shingle
|
||||
|
||||
#### Setup
|
||||
|
|
|
@ -88,12 +88,12 @@ object Module
|
|||
val engine = new ScriptEngine()
|
||||
if(logger != null){
|
||||
val ctx = engine.getContext()
|
||||
println(s"Replacing: ${ctx.getErrorWriter()}")
|
||||
// println(s"Replacing: ${ctx.getErrorWriter()}")
|
||||
ctx.setWriter(logger)
|
||||
ctx.setErrorWriter(logger)
|
||||
engine.setContext(ctx)
|
||||
}
|
||||
println(s"Replaced with: ${engine.getContext().getErrorWriter()}")
|
||||
// println(s"Replaced with: ${engine.getContext().getErrorWriter()}")
|
||||
try {
|
||||
val result = engine.eval(
|
||||
s"""net.okennedy.shingle.module.Module("$module") { implicit ctx =>
|
||||
|
|
Loading…
Reference in New Issue