https://github.com/smartenough-org/smartenough
SmartEnough is a DIY smarthome project
https://github.com/smartenough-org/smartenough
embedded esp32 homeassistant rust-lang smarthome stm32
Last synced: 2 months ago
JSON representation
SmartEnough is a DIY smarthome project
- Host: GitHub
- URL: https://github.com/smartenough-org/smartenough
- Owner: smartenough-org
- License: other
- Created: 2020-08-25T22:44:38.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2026-02-09T00:43:21.000Z (4 months ago)
- Last Synced: 2026-02-09T06:39:28.914Z (4 months ago)
- Topics: embedded, esp32, homeassistant, rust-lang, smarthome, stm32
- Language: Rust
- Homepage:
- Size: 1.27 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.org
- License: LICENSE
Awesome Lists containing this project
README
* SmartEnough
SmartEnough is an open source smart home solution that combines affordable
off-the-shelf hardware with a robust software architecture. Built for people
that don't want to pay premium for each IO they add to the system, who want to
trust the system's reliability and who are not afraid of some tinkering.
** SmartEnough design goals
- Extra cheap hardware: doable by hand (soldering iron or breadboard) and
upgradable to something more sturdy with ordered PCBs. 48+ IO per single board
possible and way cheaper $/IO than in any available commercial solutions.
- Robust, resiliant, secure: communication and power over twisted pair cables -
no batteries, no radio, no cloud.
- Supports house wiring in "constellation of star topologies". We don't have a
device in each light switch or socket, but neither are we limited to a single
central control point. Cables from lights/shutters and switches should meet
somewhere in one or more electrical boxes that are connected together with a
twisted pair cable to form a CAN bus. Bus can span multiple devices in single
electrical box, or connect multiple points in a bus or semi-bus configuration.
- Instant response to input.
- Event on one board can cause an action on another (eg. stair switches) via a
bus without requiring a computer and HomeAssistant - eg. stair lighting.
- Can gather door/window/movement sensor data and be used as an alarm system.
- Open & customizable: I'm building it to suit my needs, trying to keep it open
for any additional sensible functions.
- Integrates with HomeAssistant, but can do a lot without it.
** Resources
The core system software is in two repositories:
- [[https://github.com/smartenough-org/io-ctrl][io-ctrl]]:
Firmware for IO controller board that handles IO - reads switches and
sensors, changes outputs. Contains also firmware for hardware part (left side)
of =CAN<->USB<->MQTT= bridge to talk to HomeAssistant.
- [[https://github.com/smartenough-org/io-gate][io-gate]]:
computer part of =CAN<->USB<->MQT= bridge (right part) to convert CAN
messages to MQTT events that can be understood by HomeAssistant.
- Firmware is in Rust, written with Embassy framework for STM32G431 device.
Should migrate easy enough to other chips assuming enough peripherals are
available (CAN and USB working together, 128kB+ Flash, 32kB+ RAM).
Rest of the resources include:
- KiCAD (schematic + board) designs for IO controller board (can be used for
gate as well).
- KiCAD for organized power injection with protection.
- KiCAD for additional ESPHOME boards for less critical components (like
temperature sensors).
- 3D printing (FreeCad) designs for DIN rail (mount in electrical boxes) and
other project boxes for boards (OpenSCAD).
- This repository in addition can contain anything smarthome related I might
publish (eg. some micropython watering experiments)
** Example deployment
[[media/deployment-diagram.png]]
That's my currently working deployment. NOTE: CAN should not be a star, it
should be a bus. Hence in one case I send CAN signal back over another cable
pair in the same cable to "flatten" it out. Bus gets longer (it's around 50m
total), but stubs are shorter.
*** Connecting cables
I use two pairs for power, one for CAN and one for optional CAN return and a bit
weird RJ45 wiring to indicate the cable is a "SMART" cable not Ethernet. I also
mark those in a visible way. Anything will work as long as CAN and FORWARD is in
the same twisted pair (my mapping will work with normal T568B too).
| T568B | CAN | | |
|-------+------+---+-----------------------|
| w-o | w-o | 1 | CAN_L |
| o | o | 2 | CAN_H |
| w-g | w-g | 3 | IN POWER, 24V |
| bl | g | 4 | IN POWER, GND (swap!) |
| w-bl | w-bl | 5 | IN POWER, 24V |
| g | bl | 6 | IN POWER, GND (swap!) |
| w-br | w-br | 7 | CAN_L FORWARD |
| br | br | 8 | CAN_H FORWARD |
*** CAN configuration
I use CAN because it's a multi-master bus, no "leader" device on the BUS needs
to poll for data from "following" devices. When input event occurs or output
changes state a board broadcasts a message on the bus. Another board can see
this message and react by changing it's outputs.
Gate is a special device that serves as a bidirectional =CAN<->USB<->MQTT=
bridge. It receives CAN messages, converts them and publishes them on MQTT. It
also subscribes to MQTT topics and if something is published there it sends a
CAN request to for example toggle an Output.
I use 250kbps CAN speed and 11-bit addressing. I opted for a simple CAN protocol
(as opposed to more versatile CANopen). Address relates to a "message" more than
a "sender/receiver" and is used in determining the priority on the bus. Given
that:
- Messages must be properly unique,
- lower values have higher priorities,
- we want at least 64 devices on the bus,
I picked 6 bit for device address and 5 for message type (32 different message
types). Format: =TTTTTAAAAAA (T)ype + (A)ddress=.
Reporting errors, propagating output/input changes, setting output has higher
priority than requesting status, reporting status, time announcements or some
debug ping/pong messages.
Message body consists of up to 8 bytes of data, system typically uses 2-3.
Example: Request output change has 2 bytes: Index of output to change and byte
representing state (Off, On, Toggle). Message address points at the device that
should change output ("destination").
Message "Output changed" has similarly output index and state (Off, On), but
address points to a message source instead. I don't use RTR (remote frames).
Conscise list of used commands (but see message.rs for details):
- ERROR 0x02 - Error happened.
- OUTPUT_CHANGED 0x04 - My output changed
- INPUT_CHANGED 0x05 - My input was changed
- SET_OUTPUT 0x08 - Set output X to Y (or invert state)
- CALL_PROC 0x0A - Call a predefined procedure in VM
- CALL_SHUTTER 0x0B - Pass command to Shutter code
- STATUS_IO 0x0E - My current IO status, not necessarily changed.
- INFO 0x12 - Similar to ERROR, but low priority (eg. Device started)
- PONG 0x1D
- PING 0x1E
Call Shutter is longest command as it includes a shutter index and a command
byte that can contain a height and a tilt of the shutter.
** IO Controller MainBoard
For details on components and software see
[[https://github.com/smartenough-org/io-ctrl][io-ctrl]].
This board controls IOs when paired with some relay/SSR module. It sits in an
electrical box where it can read signals from light switches and control power
to lighting. It's talks with the world via classical twisted pair cable: CAT5e
UTP. Cable carries power (24V+) and a CAN bus.
[[hardware/board_v1.png]]
[[hardware/schematic_v1.png]]
** Power distribution board
Power board distributes power with some protection (capacitors, resettable
individual fuses, main fuses, zener diodes to limit voltage, diodes to prevent
invalid polarization). It also connects CAN BUS together in configured various
ways (directly, or using FORWARD pair). In general it allows me to connect the
cables from boards in the main central hub easily.
[[hardware/powerboard_v1.png]]
** ESPHome "Uniboard"
It's not strictly part of my main smarthome. A universal PCB board for ESP32 S2
Mini modules I have. It has power stabilization, 1-wire pull-up, some analog
inputs, RS485 interface, four MOSFETs for RGBW or anything else (garage door
control).
I use it with Esphome (over Wifi) where I can't reach with my CAN bus, or where
I don't need the resiliency or just temporarily. For example to gather
temperature readings around heat pump.
[[hardware/uniboard.png]]
** Greenfinger
Automatic plant watering using ESP8266 (or ESP32) using Micropython.
Integrates with HomeAssistant over MQTT:
- Reports status (humidity, operations).
- Can be controlled over MQTT (more water NOW).
It was 100% stable during a period of about a year. Plants died for unrelated
reasons. ;)