SIMO.io Quick Start Guide
Set up your wire‑first SIMO.io system: place the hub, create an instance, pair Game Changer boards, and build your first automations.
Describe an outcome. Get a clean Python script in ~60 seconds. Adjust it when you want in SIMO.io Admin. Fewer surprises, calmer results.
Homes don’t run on rules; they run on rhythm. People wake up early in winter and late in summer. Guests arrive without warning. School bags get dropped by the hallway sensor every afternoon. Most automation systems try to tame that with diagrams, checkboxes, and pages of options. SIMO.io takes a simpler path: you describe the outcome in plain language, we produce a clean Python script you can read, and your SIMO.io hub carries it out. The goal is simple: predictable behavior that feels natural, without a weekend lost to debugging.
If you’ve ever fought a fragile rules engine, you already know the failure modes: one broken link, one renamed scene, one bit of indentation in a YAML file—and the whole routine doesn’t fire. The difference here isn’t just technology. It’s posture. We treat automation as software, not a puzzle. Scripts are standard, inspectable, and easy to adjust. You can tell what they do at a glance, you can explain them to someone else, and you can trust them to behave the same way in August as they do in February.
Write what you want to happen. SIMO.io turns that into a Python script in about a minute and adds it to your home as a first‑class component. From there it does the boring work the right way: listen for events, check if now is the right time, and act with restraint. One gentle note on the path from request to result: the script is generated in the SIMO.io cloud once, then it runs on your SIMO.io hub from that point onward. That’s it. What matters more is how it feels to live with it.
We aim for three sensations that make a home feel considered rather than automated:
Automation rules can look friendly at first. Then the edge cases show up. A “simple” adjustment to quiet‑hours ends up touching five places. A renamed room breaks an include you didn’t know was there. A copy‑pasted block keeps an old ID lurking in it. Systems that hide complexity in boxes and lines often make it harder to see what will happen next.
Python scripts are plain language for behavior. You can read a function called on_motion and know what it does. You can keep logic in one place instead of four. You can extract a guard like “is it after dark?” and reuse it across rooms. When something goes wrong, the log points to a specific line, not a silent black hole. And when your projects get serious—multi‑room, multi‑floor, multi‑tenant—the same standard tools work: naming, versioning, code review, shared helpers, tests if you want them. No mysteries. No spelunking.
We’ve seen homes with a dozen motion sensors and still‑flickery hallway lights. We’ve seen heating rules that behave like a metronome—on, off, on, off—because the weather wasn’t part of the conversation. The scripts SIMO.io generates favor calm decisions over busy ones. They check the current state, make a change only when it improves things, and never fight a human who just made a choice at the switch.
Here’s the texture of day‑to‑day:
The pattern is consistent: scripts listen; they check a guard; they act with restraint. If someone chooses a different level by hand, a good script won’t rush to override it. That’s not a special toggle—it’s a posture.
You write a line or two in the SIMO.io app—“When hallway motion is detected after dark, lift lights to 30% and hold for 2 minutes”—and save. About a minute later, a Script component appears. That’s your Python script. You can run it like any other component, you can see its description, and, if you want to change how it works, you can open it in SIMO.io Admin and edit it directly.
For precision, include IDs in your request when you know them—component IDs, zone IDs, category IDs. Names can change; IDs don’t. But you don’t need to be formal to get started. Natural language is enough for a first pass; you can iterate.
Let’s walk a hallway most homes recognize. It’s the path between bedrooms and kitchen, the late‑night water run, the route children turn into a track. You want it to be helpful at night and invisible during the day. You want guests to feel welcome without fuss. Here’s the exact request and the script SIMO.io produces.
“When motion is detected in the Hallway (zone 12) after dark and hallway brightness is below 50 lux, set corridor lights to 30% and keep them on for 2 minutes after the last motion. If someone manually sets a higher level, don’t lower it. Double‑clicking the hallway button (component 455) toggles a 20‑minute guest mode: hold lights at 60% and skip auto‑off. Corridor lights are in category 3. Motion sensor ID is 812. Lux sensor ID is 710.”
Generation takes roughly a minute. SIMO.io returns a Python script plus a short description that appears in the app. You can run it as-is, or open SIMO.io Admin to refine details.
from django.db.models import Q
from django.utils import timezone
import time
from simo.core.models import Component
from simo.generic.scripting.helpers import LocalSun
class Automation:
# IDs and thresholds
LIGHTS_CATEGORY = 3 # "Lights" category
HALLWAY_ZONE_ID = 12 # Hallway zone
MOTION_SENSOR_ID = 812 # Motion/presence sensor (binary-sensor)
LUX_SENSOR_ID = 710 # Lux sensor (numeric-sensor)
BUTTON_ID = 455 # Hallway button (button)
TARGET_DIM = 30 # % for normal presence lighting
GUEST_DIM = 60 # % during guest mode
HOLD_SECONDS = 120 # 2 minutes
GUEST_MODE_SECONDS = 20 * 60 # 20 minutes
DARK_LUX = 50 # lux threshold for "dark"
def __init__(self):
self.last_motion_ts = 0
self.guest_mode_until = 0
self.managed = {} # comp_id -> level we set ('on' or int %)
self.light_watch = set()
def now(self):
return timezone.localtime().timestamp()
def in_guest_mode(self):
return self.now() < self.guest_mode_until
def is_dark(self):
lux = Component.objects.filter(id=self.LUX_SENSOR_ID, base_type='numeric-sensor').first()
if lux and lux.value is not None:
try:
return float(lux.value) < self.DARK_LUX
except Exception:
pass
return LocalSun().is_night()
def corridor_lights(self):
return Component.objects.filter(
zone_id=self.HALLWAY_ZONE_ID,
category_id=self.LIGHTS_CATEGORY,
base_type__in=('switch', 'dimmer', 'rgbw-light')
)
def on_light_change(self, comp, actor=None):
prev = self.managed.get(comp.id)
if prev is None:
return
try:
if comp.base_type == 'dimmer':
current = comp.value if isinstance(comp.value, (int, float)) else None
if current is not None and int(current) != int(prev):
self.managed.pop(comp.id, None)
else:
self.managed.pop(comp.id, None)
except Exception:
self.managed.pop(comp.id, None)
def ensure_watch_lights(self):
for comp in self.corridor_lights().exclude(id__in=self.light_watch):
comp.on_change(self.on_light_change)
self.light_watch.add(comp.id)
def set_light_level(self, comp, level):
try:
if comp.base_type == 'dimmer':
current = comp.value if isinstance(comp.value, (int, float)) else 0
# Only raise; do not lower manual overrides
if float(current or 0) + 0.1 < level:
print(f"[Hallway] Set dimmer {comp.id} to {level}%")
comp.send(int(level))
self.managed[comp.id] = int(level)
else:
if not comp.value:
print(f"[Hallway] Turn on light {comp.id}")
comp.turn_on()
self.managed[comp.id] = 'on'
except Exception as e:
print(f"[Hallway] Failed to set light {comp.id}: {e}")
def turn_off_managed(self):
for comp in self.corridor_lights():
if comp.id not in self.managed:
continue
try:
if comp.base_type == 'dimmer':
expected = self.managed.get(comp.id)
current = comp.value if isinstance(comp.value, (int, float)) else None
if current is not None and int(current) == int(expected):
print(f"[Hallway] Auto-off dimmer {comp.id}")
comp.turn_off()
else:
if comp.value:
print(f"[Hallway] Auto-off light {comp.id}")
comp.turn_off()
except Exception as e:
print(f"[Hallway] Failed to turn off {comp.id}: {e}")
self.managed.clear()
def on_motion(self, sensor, actor=None):
if sensor.value:
self.last_motion_ts = self.now()
print("[Hallway] Motion detected")
if self.in_guest_mode():
for comp in self.corridor_lights():
self.set_light_level(comp, self.GUEST_DIM)
return
if self.is_dark():
for comp in self.corridor_lights():
self.set_light_level(comp, self.TARGET_DIM)
else:
print("[Hallway] Motion cleared")
def on_button(self, btn, actor=None):
if btn.value == 'double-click':
if self.in_guest_mode():
self.guest_mode_until = 0
print("[Hallway] Guest mode OFF")
else:
self.guest_mode_until = self.now() + self.GUEST_MODE_SECONDS
print("[Hallway] Guest mode ON (20 min)")
for comp in self.corridor_lights():
self.set_light_level(comp, self.GUEST_DIM)
def run(self, exit):
motion = Component.objects.filter(id=self.MOTION_SENSOR_ID, base_type='binary-sensor').first()
if motion:
motion.on_change(self.on_motion)
btn = Component.objects.filter(id=self.BUTTON_ID, base_type='button').first()
if btn:
btn.on_change(self.on_button)
self.ensure_watch_lights()
while not exit.is_set():
time.sleep(1)
self.ensure_watch_lights()
if not self.in_guest_mode() and self.last_motion_ts:
if self.now() - self.last_motion_ts > self.HOLD_SECONDS:
print("[Hallway] No motion; auto-off lights I set")
self.turn_off_managed()
self.last_motion_ts = 0
“When the hallway motion sensor (ID 812) detects movement after dark (lux sensor 710 < 50 lx or after sunset), the script raises corridor lights (category 3 in zone 12) to 30% and keeps them on for 2 minutes after the last motion. If someone manually sets a higher level, the script will not lower it. A double‑click on the hallway button (ID 455) toggles Guest Mode for 20 minutes: lights are held at 60% and the auto‑off is skipped. The script listens to sensor and button events and only turns off the lights it turned on.”
Two details worth noting. First, the script never argues with a person—it won’t lower a manual override. Second, the auto‑off only targets lights it turned on, not everything in the zone. That’s the difference between living with automations and living inside them.
Requests don’t need to be formal. Start with normal language and add specifics when you know them. The generator understands zones, categories, and IDs; the more precise you are, the less guessing it has to do. A few patterns help:
If you’re not sure about IDs, ask the app: long‑press a component to see its details, or browse by category. You can always refine the request later—regenerating the script is fast.
Every script that behaves well tends to read the same way: an event arrives, a guard decides if it’s the right moment, and an action makes the change. That’s not a style preference; it’s a reliability habit. The shape makes it obvious what happens, when, and why.
It’s a small discipline that pays back on day one and again on day 300—especially when someone else has to read the script after you.
The SIMO.io app is the fastest way to describe and deploy. When you want to refine behavior, open SIMO.io Admin. The script is right there, readable, editable, with live logs at your side. You can factor out a shared helper, tidy naming, and keep a consistent style across rooms and floors. The hub executes the script after generation; your edits apply immediately.
None of this demands a “developer” title. It rewards anyone who wants a home to behave with precision without turning into a hobby.
Homes have people in them. Good scripts respect that. A few guidelines we like and the generator favors:
The result is a home that feels like it understands you rather than second‑guesses you.
Once you get the taste for scripts you can read, it’s hard to go back to boxes and lines. These are the kinds of everyday wins that show up early:
Each of these reads as plain intent. Each becomes a Python script that’s easy to revisit three months later when you decide you prefer 25 minutes to 20.
Homes grow, projects evolve, preferences change. The long‑term cost of an automation system isn’t in the first setup; it’s in the fifth change. A Python script that says exactly what it does is future‑proof in a way a chain of rules never quite is. The minute you see the pattern—event, guard, action—you can scan a script and know where to change it. There are fewer places for “that one hidden dependency” to hide.
It’s also easier to scale a way of working. If you’re an integrator, you can keep a small set of helpers—guards for quiet hours, presence heuristics, target curves for dimming—and drop them into new homes with confidence. If you’re a homeowner who likes to tinker, you can keep your own archive of scripts that feel right for your spaces. Either way, tweaks are fast because the shape stays familiar.
The best compliment we hear is simple: “I forgot it was there.” That’s the job. Automations should fade into the background until you need them—and then be obvious enough to change in one pass.
Describe outcomes. Get a Python script. Live in a home that behaves with you, not at you.
Set up your wire‑first SIMO.io system: place the hub, create an instance, pair Game Changer boards, and build your first automations.