{"id":17624736,"url":"https://github.com/martinohmann/rfoutlet","last_synced_at":"2025-05-04T08:38:50.832Z","repository":{"id":33241464,"uuid":"156522029","full_name":"martinohmann/rfoutlet","owner":"martinohmann","description":"Control remote controlled outlets via Raspberry PI","archived":false,"fork":false,"pushed_at":"2023-03-06T23:20:39.000Z","size":5994,"stargazers_count":19,"open_issues_count":28,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T21:33:24.973Z","etag":null,"topics":["diy","golang","gpio","home-automation","outlet","raspberry-pi","react"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinohmann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-07T09:28:42.000Z","updated_at":"2024-12-12T21:27:05.000Z","dependencies_parsed_at":"2024-06-21T12:59:25.197Z","dependency_job_id":"7681cd72-73bd-4604-8205-a0670b10ce27","html_url":"https://github.com/martinohmann/rfoutlet","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinohmann%2Frfoutlet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinohmann%2Frfoutlet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinohmann%2Frfoutlet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinohmann%2Frfoutlet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinohmann","download_url":"https://codeload.github.com/martinohmann/rfoutlet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252136937,"owners_count":21700104,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["diy","golang","gpio","home-automation","outlet","raspberry-pi","react"],"created_at":"2024-10-22T22:05:15.494Z","updated_at":"2025-05-03T03:22:13.241Z","avatar_url":"https://github.com/martinohmann.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"rfoutlet\n========\n\n[![Build Status](https://github.com/martinohmann/rfoutlet/workflows/build/badge.svg)](https://github.com/martinohmann/rfoutlet/actions?query=workflow%3Abuild)\n[![codecov](https://codecov.io/gh/martinohmann/rfoutlet/branch/master/graph/badge.svg)](https://codecov.io/gh/martinohmann/rfoutlet)\n[![Go Report Card](https://goreportcard.com/badge/github.com/martinohmann/rfoutlet)](https://goreportcard.com/report/github.com/martinohmann/rfoutlet)\n[![PkgGoDev](https://pkg.go.dev/badge/github.com/martinohmann/rfoutlet)](https://pkg.go.dev/github.com/martinohmann/rfoutlet)\n\nOutlet control via web interface for Raspberry PI 2/3/4. The transmitter and\nreceiver logic has been ported from the great\n[rc-switch](https://github.com/sui77/rc-switch) C++ project to golang.\n\n![Raspberry PI Setup](assets/setup.jpg)\n\nContents\n--------\n\n- [Screenshots](#screenshots)\n- [Stability note](#stability-note)\n- [Breaking changes](#breaking-changes)\n- [Prerequisites](#prerequisites)\n- [Installation](#installation)\n- [Commands](#commands)\n- [Raspberry PI Setup](#raspberry-pi-setup)\n- [Outlets](#outlets)\n- [Running rfoutlet as systemd service](#running-rfoutlet-as-systemd-service)\n- [Development / Testing](#development--testing)\n- [Todo](#todo)\n- [License](#license)\n- [Resources](#resources)\n\nScreenshots\n-----------\n\nSome screenshots of the web app that controls the outlets.\n\nMain Outlet View                             | Schedule View                                 | Settings View\n:------------------------------------------: | :-------------------------------------------: | :---------------------------------------------------:\n![Screenshot](assets/screenshot_outlets.jpg) | ![Screenshot](assets/screenshot_schedule.jpg) | ![Raspberry PI Setup](assets/screenshot_settings.jpg)\n\nStability note\n--------------\n\nThe *master* branch may be broken at any time. Please check out the latest tag\nor use the latest [release](https://github.com/martinohmann/rfoutlet/releases).\n\nBreaking changes\n----------------\n\n### v0.5.0 to v1.0.0\n\nDue to a complete rewrite of the internal logic, many API inconsistencies have\nbeen fixed. This introduces non-backwards-compatible changes.\n\n- The config file format changed completely, please have a look at [the\n  example](configs/config.yml) and adjust your config accordingly.\n- The state file format changed, so that old file cannot be loaded with the new\n  version. It is advised to start with a fresh state file. If you have a lot of\n  state, make a backup before upgrading and manually convert the state file\n  json to the new format. In the following example `foo` and `bar` are the IDs\n  of the outlets in the state file.\n\n  Old format:\n  ```json\n  {\"switch_states\":{\"bar\":1,\"foo\":1},\"schedules\":{\"foo\":[{\"enabled\": true,\"weekdays\":[1],\"from\":{\"hour\":0,\"minute\":59},\"to\":{\"hour\":2,\"minute\":1}}]}}\n  ```\n  New format:\n  ```json\n  {\"bar\":{\"state\":1},\"foo\":{\"state\":1,\"schedule\":[{\"enabled\": true,\"weekdays\":[1],\"from\":{\"hour\":0,\"minute\":59},\"to\":{\"hour\":2,\"minute\":1}}]}}\n  ```\n- `rfoutlet serve`:\n  - `--gpio-pin` flag was renamed to `--transmit-pin` as it now\n    also supports `--receive-pin` for state drift detection.\n- `rfoutlet sniff`:\n  - `--gpio-pin` flag was renamed to `--pin`.\n- `rfoutlet transmit`:\n  - `--gpio-pin` flag was renamed to `--pin`.\n  - The command now accepts a list of codes that are transmitted sequentially.\n- The websocket message format changed slightly, so the web frontend needs to\n  be rebuilt (see [installation](#installation) section).\n- In the package `pkg/gpio` the usage of\n  [gpio](https://github.com/brian-armstrong/gpio) was replaced with\n  [gpiod](https://github.com/warthog618/gpiod) to get rid of the dependency on\n  the deprecated GPIO interface which may be removed from the linux kernel this\n  year. This was also a good opportunity to improve the public API of\n  `pkg/gpio`.\n- Instead of `/dev/gpiomem`, rfoutlet now depends on `/dev/gpiochip0`.\n- Since v1.0.0 does not depend on the sysfs anymore, the GPIO pins have to be\n  unexported there to avoid `device busy` errors. This can be done like this:\n  ```bash\n  # Replace 17 and 27 with the GPIO pin you are using for transmitting and\n  # receving rf codes if you are not using the defaults.\n  echo \"17\" \u003e /sys/class/gpio/unexport\n  echo \"27\" \u003e /sys/class/gpio/unexport\n  ```\n\nPrerequisites\n-------------\n\nSee the [Raspberry PI Setup](#raspberry-pi-setup) section for setup of hardware\nand required software.\n\n### Hardware\n\n- Raspberry PI 2, 3 or 4\n- Remote controlled outlets (see [Outlets](#outlets) section for suggestions)\n- Receiver/Transmitter (e.g.\n  [this](https://www.amazon.com/SMAKN%C2%AE-433Mhz-Transmitter-Receiver-Arduino/dp/B00M2CUALS/ref=sr_1_3?s=electronics\u0026ie=UTF8\u0026qid=1541529103\u0026sr=1-3\u0026keywords=433mhz+receiver+transmitter))\n- SD Card\n- Power supply\n- Wiring\n- Breadboard (optional)\n\n### Software\n\n- I use Arch Linux on the Raspberry PI, but Raspbian should also work\n- nodejs 15.0+\n- golang 1.13+\n- `make`\n\nOlder software versions may also work, but I did not test that.\n\nInstallation\n------------\n\n### Using `go get`\n\nObtain the source, build and install it as follows:\n\n```sh\ngo get -u github.com/martinohmann/rfoutlet\ncd $GOPATH/src/github.com/martinohmann/rfoutlet\nmake all\nmake install\n```\n\nYou will find a new binaries below `$GOPATH/bin`: `rfoutlet`.\n\nIf you only want to use the gpio transmitter and receiver code below\n[pkg/gpio/](pkg/gpio/) for your own project, just `go get` the project and\ncheck out the code in [cmd/sniff.go](cmd/sniff.go) and\n[cmd/transmit.go](cmd/transmit.go) for example usage.\n\n```sh\ngo get -u github.com/martinohmann/rfoutlet/pkg/gpio\n```\n\n## Using docker\n\nPre-built images of tagged releases and `master` are available on [Docker\nHub](https://hub.docker.com/r/mohmann/rfoutlet). `mohmann/rfoutlet:latest` will\nalways point to the latest tagged release.\n\nIf you prefer building locally, run:\n\n```sh\ndocker build -t mohmann/rfoutlet .\n```\n\n\n### Running via docker-compose\n\nSimply run:\n\n```sh\ndocker-compose up -d\n```\n\nThis pulls `mohmann/rfoutlet:latest` and starts the `rfoutlet` container listening on port\n`3333`.\n\n### Running via docker\n\nStart the container and browse to `\u003craspberry-ip-address\u003e:3333`:\n\n```sh\ndocker run \\\n    --rm \\\n    --privileged \\\n    -p 3333:3333 \\\n    -v /etc/localtime:/etc/localtime:ro \\\n    -v $(pwd)/configs/config.yml:/etc/rfoutlet/config.yml:ro \\\n    mohmann/rfoutlet:latest\n```\n\nThe container has to run in privileged mode in order to be able to access\n`/dev/gpiochip0`.\n\nCommands\n--------\n\nNote: all commands requires `sudo` in order to access `/dev/gpiochip0`.\n\n### `serve` command\n\nThis command starts a server which listens on `0.0.0.0:3333` by default.\n\nBy default it looks for its configuration file at `/etc/rfoutlet/config.yml`.\nCheck [configs/config.yml](configs/config.yml) for an example config file with\nall available config values. Use the `sniff` command for reading the on/off\ncodes, protocol and pulse lengths for your outlets to put into the\nconfiguration file.\n\nStart the server:\n\n```sh\nsudo rfoutlet serve --listen-address 0.0.0.0:3333 \\\n  --config /etc/rfoutlet/config.yml --transmit-pin 17\n```\n\nBy default rfoutlet uses gpio pin 17 (physical 11 / wiringPi 0) for\ntransmission of the rf codes. A different pin can be use by providing the\n`--transmit-pin` flag. Check out the [Raspberry Pi pinouts](https://pinout.xyz/) for\nreference.\n\nIf you want the outlet switch states to be persisted, pass the `--state-file` flag, e.g:\n\n```sh\nsudo rfoutlet serve --state-file /var/lib/rfoutlet/state.json\n```\n\n### `sniff` command\n\nThis command listens on a gpio pin and tries to sniff codes sent out by 433 Mhz\nremote controls. It will print the received code, protocol, pulse length and\nbit length to stdout when you press the on/off buttons on your remote.\n\n```sh\nsudo rfoutlet sniff --pin 27\n```\n\n### `transmit` command\n\nThis command sends out remote control codes on the provided gpio pin. It can be used\nfor testing or you can wrap it for use in another application.\n\nExample for sending out the code `123456`:\n\n```sh\nsudo rfoutlet transmit --pin 17 --protocol 1 --pulse-length 189 123456\n```\n\nRaspberry PI Setup\n------------------\n\n### Install required software\n\nOn Arch Linux the following commands should be sufficient to install the\nrequired software:\n\n```sh\nsudo pacman -Sy go nodejs npm make\n```\n\nOn Raspbian the following should do (untested):\n\n```sh\nwget https://storage.googleapis.com/golang/go1.15.5.linux-armv6l.tar.gz\nsudo tar -C /usr/local -xvf go1.15.5.linux-armv6l.tar.gz\nrm go1.15.5.linux-armv6l.tar.gz\ncurl -sL https://deb.nodesource.com/setup_15.x | sudo -E bash -\nsudo apt-get install -y build-essential nodejs\n```\n\nSet up `$GOPATH` afterwards:\n\n```sh\ncat \u003e\u003e ~/.bashrc \u003c\u003c 'EOF'\nexport GOPATH=$HOME/go\nexport PATH=/usr/local/go/bin:$PATH:$GOPATH/bin\nEOF\nsource ~/.bashrc\n```\n\n### Wiring transmitter and receiver\n\nThe wiring of transmitter and receiver is straight forward and can be best\ndescribed using images:\n\nTransmitter                            | Receiver\n:-------------------------------------:|:-------------------------------:\n![Transmitter](assets/transmitter.jpg) | ![Receiver](assets/receiver.jpg)\n\nTo increase the range of the transmitter I initially used a 25cm wire as antenna. I just\ntwisted it with a pair of pliers to hold it in place, soldering is optional.\nThis covers my whole appartment (105sqm). YMMV. Switched to [transmitters and\nreceivers with antennas already soldered\non](https://www.amazon.de/gp/product/B071J2Z3YK/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8\u0026language=en_GB\u0026psc=1)\nlater.\n\nOutlets\n-------\n\nI achieved good results with the following remote controlled outlets:\n\n- [Etekcity Remote Control Outlet Wireless Light Switch](https://www.amazon.com/Etekcity-Household-Appliances-Unlimited-Connections/dp/B00DQELHBS/ref=sr_1_4?ie=UTF8\u0026qid=1541529214\u0026sr=8-4\u0026keywords=etekcity+remote+control+outlet+wireless)\n- [Brennenstuhl RCS 1000 N Comfort](https://www.amazon.de/gp/product/B001AX8QUM/ref=oh_aui_detailpage_o00_s00?ie=UTF8\u0026psc=1)\n\nPlease let me know about others that work well too, so I can extend the list here.\n\nRunning rfoutlet as systemd service\n-----------------------------------\n\nSee [init/systemd/rfoutlet.service](init/systemd/rfoutlet.service) for an\nexample systemd service file.\n\nDevelopment / Testing\n---------------------\n\nrfoutlet is meant to run on a Raspberry PI 2/3/4 to work properly. However, for\ndevelopment purposes you can also run it on your local machine. If your\ndevelopment box does not have `/dev/gpiochip0`, you can load the `gpio-mockup`\nkernel module to create a mockup:\n\n```bash\nsudo make load-gpio-mockup\n```\n\nTo unload the gpio-mockup kernel module again, run:\n\n```bash\nsudo make unload-gpio-mockup\n```\n\nA more convenient way to automatically load the `gpio-mockup` kernel module and\nunload it again is to simply pass the `--gpio-mockup` flag to rfoutlet:\n\n```bash\nsudo rfoutlet --gpio-mockup [...]\n```\n\nRun `make` without arguments to see available commands for building and testing.\n\nTodo\n----\n\n- [x] implement code transmitter (see [cmd/transmit.go](cmd/transmit.go))\n- [x] implement code receiver (see [cmd/sniff.go](cmd/sniff.go))\n- [x] make transmitter/receiver code available as library below [pkg/gpio/](pkg/gpio/)\n- [x] persist outlet state across server restarts\n- [x] use receiver to detect outlet state changes (see `--detect-state-drift`\n  flag of the `serve` command)\n- [x] time switch: switch outlets on/off using user defined rules (e.g. fixed\n  time or relative)\n- [x] use web sockets for communication to be able to push outlet state changes\n  to multiple clients\n\nLicense\n-------\n\nThe source code of this is released under the MIT License. See the bundled LICENSE\nfile for details.\n\n[![Creative Commons License](https://i.creativecommons.org/l/by-nc/4.0/80x15.png)](http://creativecommons.org/licenses/by-nc/4.0/)\n\nThe images belonging to this project are licensed under a [Creative Commons\nAttribution-NonCommercial 4.0 International\nLicense](http://creativecommons.org/licenses/by-nc/4.0/).\n\nResources\n---------\n\n- [Raspberry Pi pinouts](https://pinout.xyz/)\n- [Wireless Power Outlets](https://timleland.com/wireless-power-outlets/)\n- [ninjablocks 433Utils](https://github.com/ninjablocks/433Utils)\n- [rc-switch](https://github.com/sui77/rc-switch)\n- [WiringPi](https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinohmann%2Frfoutlet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinohmann%2Frfoutlet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinohmann%2Frfoutlet/lists"}