├── .gitignore ├── platformio.ini ├── lib └── readme.txt ├── .travis.yml └── src ├── MySensorsRFReceiver.h ├── MySensorsRFReceiver.cpp └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | ;env_default = pro8MHzatmega328standalone 13 | ;env_default = bluepill_f103c8bmp 14 | env_default = d1_mini 15 | ; beware, tested with nodemcu and nodemcuv2 but transport did not work. Not sure why 16 | 17 | [env:d1_mini] 18 | platform = espressif8266 19 | framework = arduino 20 | board = d1_mini 21 | upload_port = /dev/ttyUSB0 22 | 23 | [env:esp01_1m] 24 | platform = espressif8266 25 | board = esp01_1m 26 | framework = arduino 27 | upload_port = /dev/ttyUSB0 28 | lib_deps = 29 | rc-switch 30 | MySensors@2.2.0 31 | Automaton 32 | -------------------------------------------------------------------------------- /lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) http://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- readme.txt --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | Then in `src/main.c` you should use: 31 | 32 | #include 33 | #include 34 | 35 | // rest H/C/CPP code 36 | 37 | PlatformIO will find your libraries automatically, configure preprocessor's 38 | include paths and build them. 39 | 40 | More information about PlatformIO Library Dependency Finder 41 | - http://docs.platformio.org/page/librarymanager/ldf.html 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < http://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < http://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < http://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choice one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # - platformio update 39 | # 40 | # script: 41 | # - platformio run 42 | 43 | 44 | # 45 | # Template #2: The project is intended to by used as a library with examples 46 | # 47 | 48 | # language: python 49 | # python: 50 | # - "2.7" 51 | # 52 | # sudo: false 53 | # cache: 54 | # directories: 55 | # - "~/.platformio" 56 | # 57 | # env: 58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 59 | # - PLATFORMIO_CI_SRC=examples/file.ino 60 | # - PLATFORMIO_CI_SRC=path/to/test/directory 61 | # 62 | # install: 63 | # - pip install -U platformio 64 | # - platformio update 65 | # 66 | # script: 67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 68 | -------------------------------------------------------------------------------- /src/MySensorsRFReceiver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class MySensorsRFReceiver: public Machine { 7 | 8 | public: 9 | enum { IDLE, ACCEPT, IGNORE }; // STATES 10 | enum { EVT_RECEIVE, EVT_TIMER, ELSE }; // EVENTS 11 | MySensorsRFReceiver( void ) : Machine() {}; 12 | MySensorsRFReceiver& begin(uint8_t pin, uint32_t timeout); 13 | MySensorsRFReceiver& trace( Stream & stream ); 14 | MySensorsRFReceiver& trigger( int event ); 15 | int state( void ); 16 | MySensorsRFReceiver& onReceive( Machine& machine, int event = 0 ); 17 | MySensorsRFReceiver& onReceive( atm_cb_push_t callback, int idx = 0 ); 18 | MySensorsRFReceiver& receive( void ); 19 | uint32_t receivedValue; 20 | 21 | private: 22 | enum { ENT_ACCEPT, ENT_IGNORE, LOOP_IGNORE }; // ACTIONS 23 | enum { ON_RECEIVE, CONN_MAX }; // CONNECTORS 24 | atm_connector connectors[CONN_MAX]; 25 | int event( int id ); 26 | void action( int id ); 27 | RCSwitch rc; 28 | atm_timer_millis timeout_timer; 29 | }; 30 | 31 | /* 32 | Automaton::ATML::begin - Automaton Markup Language 33 | 34 | 35 | 36 | 37 | 38 | 39 | ACCEPT 40 | 41 | 42 | IGNORE 43 | 44 | 45 | IGNORE 46 | IDLE 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Automaton::ATML::end 62 | */ 63 | -------------------------------------------------------------------------------- /src/MySensorsRFReceiver.cpp: -------------------------------------------------------------------------------- 1 | #include "MySensorsRFReceiver.h" 2 | 3 | /* Add optional parameters for the state machine to begin() 4 | * Add extra initialization code 5 | */ 6 | 7 | MySensorsRFReceiver& MySensorsRFReceiver::begin(uint8_t interrupt, uint32_t timeout) { 8 | // clang-format off 9 | const static state_t state_table[] PROGMEM = { 10 | /* ON_ENTER ON_LOOP ON_EXIT EVT_RECEIVE EVT_TIMER ELSE */ 11 | /* IDLE */ -1, -1, -1, ACCEPT, -1, -1, 12 | /* ACCEPT */ ENT_ACCEPT, -1, -1, -1, -1, IGNORE, 13 | /* IGNORE */ -1, LOOP_IGNORE, -1, IGNORE, IDLE, -1, 14 | }; 15 | // clang-format on 16 | Machine::begin( state_table, ELSE ); 17 | timeout_timer.set(timeout); 18 | rc = RCSwitch(); 19 | rc.enableReceive(interrupt); 20 | return *this; 21 | } 22 | 23 | /* Add C++ code for each internally handled event (input) 24 | * The code must return 1 to trigger the event 25 | */ 26 | 27 | int MySensorsRFReceiver::event( int id ) { 28 | switch ( id ) { 29 | case EVT_RECEIVE: 30 | if(rc.available()) { 31 | if(state() == IGNORE) { 32 | // Throw away. This is necessary because the enter action is not 33 | // repeated when transitioning between identical states. It can thus 34 | // not be reset there. 35 | rc.resetAvailable(); 36 | } 37 | return true; 38 | } else { 39 | return false; 40 | } 41 | case EVT_TIMER: 42 | return timeout_timer.expired(this); 43 | } 44 | return 0; 45 | } 46 | 47 | /* Add C++ code for each action 48 | * This generates the 'output' for the state machine 49 | * 50 | * Available connectors: 51 | * push( connectors, ON_RECEIVE, 0, , ); 52 | */ 53 | 54 | void MySensorsRFReceiver::action( int id ) { 55 | switch ( id ) { 56 | case ENT_ACCEPT: 57 | receivedValue = rc.getReceivedValue(); 58 | rc.resetAvailable(); 59 | push(connectors, ON_RECEIVE, 0, 0, 0); 60 | return; 61 | case ENT_IGNORE: 62 | return; 63 | } 64 | } 65 | 66 | /* Optionally override the default trigger() method 67 | * Control how your machine processes triggers 68 | */ 69 | 70 | MySensorsRFReceiver& MySensorsRFReceiver::trigger( int event ) { 71 | Machine::trigger( event ); 72 | return *this; 73 | } 74 | 75 | /* Optionally override the default state() method 76 | * Control what the machine returns when another process requests its state 77 | */ 78 | 79 | int MySensorsRFReceiver::state( void ) { 80 | return Machine::state(); 81 | } 82 | 83 | /* Nothing customizable below this line 84 | ************************************************************************************************ 85 | */ 86 | 87 | /* Public event methods 88 | * 89 | */ 90 | 91 | MySensorsRFReceiver& MySensorsRFReceiver::receive() { 92 | trigger( EVT_RECEIVE ); 93 | return *this; 94 | } 95 | 96 | /* 97 | * onReceive() push connector variants ( slots 1, autostore 0, broadcast 0 ) 98 | */ 99 | 100 | MySensorsRFReceiver& MySensorsRFReceiver::onReceive( Machine& machine, int event ) { 101 | onPush( connectors, ON_RECEIVE, 0, 1, 1, machine, event ); 102 | return *this; 103 | } 104 | 105 | MySensorsRFReceiver& MySensorsRFReceiver::onReceive( atm_cb_push_t callback, int idx ) { 106 | onPush( connectors, ON_RECEIVE, 0, 1, 1, callback, idx ); 107 | return *this; 108 | } 109 | 110 | /* State trace method 111 | * Sets the symbol table and the default logging method for serial monitoring 112 | */ 113 | 114 | MySensorsRFReceiver& MySensorsRFReceiver::trace( Stream & stream ) { 115 | Machine::setTrace( &stream, atm_serial_debug::trace, 116 | "MYSENSORSRFRECEIVER\0EVT_RECEIVE\0EVT_TIMER\0ELSE\0IDLE\0ACCEPT\0IGNORE" ); 117 | return *this; 118 | } 119 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | // Enable debug prints to serial monitor 2 | #define MY_DEBUG 3 | 4 | // Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h 5 | //#define MY_BAUD_RATE 9600 6 | 7 | // Enables and select radio type (if attached) 8 | // RFM69 9 | #define MY_RADIO_RFM69 10 | #define MY_RFM69_NEW_DRIVER 11 | //#define MY_RFM69_ATC_MODE_DISABLED 12 | #define MY_RFM69_ATC_TARGET_RSSI_DBM (-50) // target RSSI -70dBm 13 | #define MY_RFM69_MAX_POWER_LEVEL_DBM (10) // max. TX power 10dBm = 10mW 14 | //#define MY_RFM69_TX_POWER_DBM (10) 15 | // Lower bitrate to increase reliability 16 | #define MY_RFM69_BITRATE_MSB (RFM69_BITRATEMSB_9600) 17 | #define MY_RFM69_BITRATE_LSB (RFM69_BITRATELSB_9600) 18 | #define MY_RFM69_ENABLE_ENCRYPTION 19 | #define MY_RFM69_FREQUENCY RFM69_433MHZ 20 | //#define MY_IS_RFM69HW 21 | #define MY_RF69_IRQ_PIN (5) 22 | #define MY_RF69_IRQ_NUM MY_RF69_IRQ_PIN 23 | #define MY_DEBUG_VERBOSE_RFM69 24 | 25 | #define MY_GATEWAY_ESP8266 26 | 27 | // Set the hostname for the WiFi Client. This is the hostname 28 | // it will pass to the DHCP server if not static. 29 | #define MY_ESP8266_HOSTNAME "gateway" 30 | 31 | // Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP) 32 | #define MY_IP_ADDRESS 192,168,1,126 33 | 34 | // If using static ip you can define Gateway and Subnet address as well 35 | #define MY_IP_GATEWAY_ADDRESS 192,168,1,1 36 | #define MY_IP_SUBNET_ADDRESS 255,255,255,0 37 | 38 | // Enable inclusion mode 39 | //#define MY_INCLUSION_MODE_FEATURE 40 | // Enable Inclusion mode button on gateway 41 | //#define MY_INCLUSION_BUTTON_FEATURE 42 | // Set inclusion mode duration (in seconds) 43 | //#define MY_INCLUSION_MODE_DURATION 60 44 | // Digital pin used for inclusion mode button 45 | //#define MY_INCLUSION_MODE_BUTTON_PIN 3 46 | 47 | // Set blinking period 48 | //#define MY_DEFAULT_LED_BLINK_PERIOD 300 49 | 50 | // Flash leds on rx/tx/err 51 | //#define MY_DEFAULT_ERR_LED_PIN 16 // Error led pin 52 | //#define MY_DEFAULT_RX_LED_PIN 16 // Receive led pin 53 | //#define MY_DEFAULT_TX_LED_PIN 16 // the PCB, on board LED 54 | 55 | #include 56 | #include 57 | #include 58 | #include "MySensorsRFReceiver.h" 59 | 60 | #define CHILD_ID_RF (1) 61 | #define CHILD_ID_RSSI_NODE_1 (2) 62 | #define CHILD_ID_RSSI_NODE_2 (3) 63 | #define CHILD_ID_RSSI_NODE_3 (4) 64 | #define CHILD_ID_RSSI_NODE_4 (5) 65 | 66 | #define RF_RECEIVE_PIN (4) 67 | #define TIMEOUT (1000) // require 1 second of silence between repetitions 68 | 69 | 70 | // We use an automaton to ignore doubles 71 | MySensorsRFReceiver receiver; 72 | 73 | MyMessage recvMesg(CHILD_ID_RF, V_VAR1); 74 | MyMessage msgRssi1(CHILD_ID_RSSI_NODE_1, V_LEVEL); 75 | MyMessage msgRssi2(CHILD_ID_RSSI_NODE_2, V_LEVEL); 76 | MyMessage msgRssi3(CHILD_ID_RSSI_NODE_3, V_LEVEL); 77 | MyMessage msgRssi4(CHILD_ID_RSSI_NODE_4, V_LEVEL); 78 | 79 | 80 | void presentation() 81 | { 82 | // Present locally attached sensors here 83 | present(CHILD_ID_RF, S_CUSTOM, "RF Receiver"); 84 | present(CHILD_ID_RSSI_NODE_1, S_SOUND, "RSSI"); 85 | present(CHILD_ID_RSSI_NODE_2, S_SOUND, "RSSI"); 86 | present(CHILD_ID_RSSI_NODE_3, S_SOUND, "RSSI"); 87 | present(CHILD_ID_RSSI_NODE_4, S_SOUND, "RSSI"); 88 | } 89 | 90 | void receiveCallBack(int idx, int v, int up) { 91 | // Send communications 92 | Serial.println("Sending!!"); 93 | send(recvMesg.set(receiver.receivedValue)); 94 | } 95 | 96 | void setup() 97 | { 98 | receiver 99 | //.trace(Serial) 100 | .begin(RF_RECEIVE_PIN, TIMEOUT) // interrupt # is same as PIN # 101 | .onReceive(receiveCallBack); 102 | } 103 | 104 | void loop() 105 | { 106 | automaton.run(); 107 | } 108 | 109 | void receive(const MyMessage &message) 110 | { 111 | if(message.sender == 1) { 112 | send(msgRssi1.set(RFM69_getReceivingRSSI())); 113 | } else if(message.sender == 2) { 114 | send(msgRssi2.set(RFM69_getReceivingRSSI())); 115 | } else if(message.sender == 3) { 116 | send(msgRssi3.set(RFM69_getReceivingRSSI())); 117 | } else if(message.sender == 4) { 118 | send(msgRssi4.set(RFM69_getReceivingRSSI())); 119 | } 120 | } 121 | --------------------------------------------------------------------------------