/** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. */ // Enable debug prints to serial monitor //#define MY_DEBUG // configure radio #define MY_RADIO_RFM69 /** @brief RFM69 frequency to use (RF69_433MHZ for 433MHz, RF69_868MHZ for 868MHz or RF69_915MHZ for 915MHz). */ #define MY_RFM69_FREQUENCY RF69_868MHZ /** @brief Enable this if you're running the RFM69HW model. */ #define MY_IS_RFM69HW /** @brief RFM69 Network ID. Use the same for all nodes that will talk to each other. */ #define MY_RFM69_NETWORKID 1 /** @brief Node id defaults to AUTO (tries to fetch id from controller). */ #define MY_NODE_ID 3 /** @brief If set, transport traffic is unmonitored and GW connection is optional */ #define MY_TRANSPORT_DONT_CARE_MODE /** @brief Node parent defaults to AUTO (tries to find a parent automatically). */ #define MY_PARENT_NODE_ID 0 /** @brief The user-defined AES key to use for EEPROM personalization */ #include "aes_key.h" // Enable repeater functionality for this node //#define MY_REPEATER_FEATURE /** @brief Enables RFM69 automatic transmit power control class. */ //#define MY_RFM69_ATC #ifdef MY_AES_KEY /** @brief enables RFM69 encryption */ #define MY_RFM69_ENABLE_ENCRYPTION #endif #include #include enum sensor_type : uint8_t { SENSOR_RELAY = (1u << 0), SENSOR_DIMMER = (1u << 1), SENSOR_BUTTON = (1u << 2), SENSOR_SCENE = (1u << 3), }; struct sensor_t { uint8_t id; uint8_t type; struct { uint8_t pin; // push button pin } button; }; struct sensor_t sensors[] = { { .id = 0, .type = SENSOR_BUTTON | SENSOR_SCENE, .button = { .pin = 3 }, }, }; #define NUM(a) (sizeof(a) / sizeof(*a)) #define TEMP_SENSOR_ID -1 #define TEMP_READ_INTERVAL 1000L // read temp every 1 sec #define TEMP_N_READS_MSG 60*60 // force temp message every n reads #define TEMP_OFFSET 0 MyMessage msg(0, V_SCENE_ON); inline void checkTemperature(void); void wakeUp(void); void before() { #ifdef MY_AES_KEY const uint8_t user_aes_key[16] = { MY_AES_KEY }; uint8_t cur_aes_key[16]; hwReadConfigBlock((void*)&cur_aes_key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, sizeof(cur_aes_key)); if (memcmp(&user_aes_key, &cur_aes_key, 16) != 0) { hwWriteConfigBlock((void*)user_aes_key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, sizeof(user_aes_key)); debug(PSTR("AES key written\n")); } #endif } void setup() { #ifdef MY_IS_RFM69HW _radio.setHighPower(true); #endif //_radio.setPowerLevel(10); #ifdef MY_RFM69_ATC _radio.enableAutoPower(-70); debug(PSTR("ATC enabled\n")); #endif for (uint8_t i = 0; i < NUM(sensors); i++) { struct sensor_t *sensor = &sensors[i]; if (sensor->type & SENSOR_BUTTON) pinMode(sensor->button.pin, INPUT_PULLUP); } } void presentation() { sendSketchInfo("LRSwitch", "1.0"); // register all sensors to gw (they will be created as child devices) for (uint8_t i = 0; i < NUM(sensors); i++) { struct sensor_t *sensor = &sensors[i]; if (sensor->type & SENSOR_SCENE) present(sensor->id, S_SCENE_CONTROLLER); } #if TEMP_SENSOR_ID >= 0 present(TEMP_SENSOR_ID, S_TEMP); #endif } void loop() { //TODO maybe call _radio.rcCalibration() all 1000x changes? struct sensor_t *sensor = &sensors[0]; uint8_t pin = sensor->button.pin; // delay() instead of sleep() // sleep() will for whatever reason trigger the external interrupt?! delay(1000); Serial.println("r"); Serial.flush(); uint8_t state_before = digitalRead(pin); int8_t intr = sleep(digitalPinToInterrupt(pin), CHANGE, 0); if (intr == digitalPinToInterrupt(pin)) { uint8_t state_now = digitalRead(pin); if (state_before != state_now) { Serial.println("m"); send(msg.setType(V_SCENE_ON).setSensor(sensor->id).set(1)); } } #if TEMP_SENSOR_ID >= 0 checkTemperature(); #endif } inline void checkTemperature(void) { static unsigned long lastTempUpdate = millis(); static unsigned int numTempUpdates = 0; static float lastTemp = 0; static MyMessage msgTemp(TEMP_SENSOR_ID, V_TEMP); unsigned long now = millis(); if (now - lastTempUpdate > TEMP_READ_INTERVAL) { float temp = _radio.readTemperature() + TEMP_OFFSET; lastTempUpdate = now; if (isnan(temp)) Serial.println(F("Failed reading temperature")); else if (abs(temp - lastTemp) >= 2 || numTempUpdates == TEMP_N_READS_MSG) { lastTemp = temp; numTempUpdates = 0; send(msgTemp.set(temp, 2)); #ifdef MY_DEBUG char str_temp[6]; dtostrf(temp, 4, 2, str_temp); debug(PSTR("Temperature: %s °C\n"), str_temp); #endif } else ++numTempUpdates; } }