#include // HeatpumpIR libraries #include #include #include #include #include #include #include // Timer library, https://github.com/ToniA/Timer #include // MySensors libraries #include #include // This MySensors node has three childs, with ID's 1, 2 & 3 #define CHILD_1 1 #define CHILD_2 2 #define CHILD_3 3 // MySensors definitions MySensor gw; MyMessage irMsg(CHILD_1, V_IR_RECEIVE); // Domoticz does not yet properly support the S_IR sensor type MyMessage textMsg(CHILD_2, V_TEXT); MyMessage sendMsg(CHILD_3, V_LIGHT); // Array with all supported heatpump models HeatpumpIR *heatpumpIR[] = { new PanasonicCKPHeatpumpIR(), // 0, keep this if you don't remove the timer for cancelling Panasonic CKP messages new PanasonicDKEHeatpumpIR(), // 1 new PanasonicJKEHeatpumpIR(), // 2 new PanasonicNKEHeatpumpIR(), // 3 new CarrierHeatpumpIR(), // 4 new MideaHeatpumpIR(), // 5 new FujitsuHeatpumpIR(), // 6 new MitsubishiFDHeatpumpIR(), // 7 new MitsubishiFEHeatpumpIR(), // 8 new SamsungHeatpumpIR() // 9 }; // IR led on PWM output-capable digital pin 3 IRSender irSender(3); // Timer for sending Panasonic CKP series timer cancellation commands Timer timer; int8_t panasonicCKPTimer = 0; // Number of supported models byte models = 0; void setup() { Serial.begin(115200); delay(1000); Serial.println(F("HeatpumpIR sensor starting up...")); models = sizeof(heatpumpIR) / sizeof(HeatpumpIR*); Serial.print(F("Number of supported models: ")); Serial.println(models); // Auto-assign the node ID, do not forward messages gw.begin(incomingMessage, AUTO, false); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Heatpump Sensor", "1.0"); // Register a sensors to the MySensors Gateway gw.present(CHILD_1, S_IR, "IR sender"); // For Domoticz gw.present(CHILD_2, S_INFO, "IR data"); gw.present(CHILD_3, S_LIGHT, "IR send"); // The TEXT sensor is not created in Domoticz before data is sent gw.send(textMsg.setSensor(CHILD_2).set("00000000")); } void loop() { gw.process(); timer.update(); } // Handle incoming messages from the MySensors Gateway void incomingMessage(const MyMessage &message) { const char *irData; // V_IR type message if (message.type==V_IR_SEND) { Serial.println(F("Received IR send command...")); irData = message.getString(); Serial.print(F("Code: 0x")); Serial.println(irData); sendHeatpumpIRCommand(irData); } // Domoticz else if (message.type==V_LIGHT) { // When the button is pressed on Domoticz, request the value of the TEXT sensor Serial.println(F("Requesting IR code from Domoticz...")); gw.request(CHILD_2, V_TEXT, 0); } else if (message.type==V_TEXT) { // TEXT sensor value is received as a result of the previous step Serial.println(F("IR code received from Domoticz...")); Serial.print(F("Code: 0x")); irData = message.getString(); Serial.println(irData); sendHeatpumpIRCommand(irData); // Set the Domoticz switch back to 'OFF' state gw.send(sendMsg.setSensor(CHILD_3).set(0)); } } // Decode the IR command and send the IR command to the heatpump void sendHeatpumpIRCommand(const char *irCommandString) { // irCommandString is an 8-digit hex digit long irCommand = 0; int sscanfStatus = sscanf(irCommandString, "%lx", &irCommand); if (sscanfStatus == 1) { Serial.print(F("IR code conversion OK: 0x")); Serial.println(irCommand, HEX); } else { Serial.println(F("Failed to convert IR hex code to number")); } /* The heatpump command is packed into a 32-bit hex number, see libraries\HeatpumpIR\HeatpumpIR.h for the constants 12345678 3 MODEL 4 POWER 5 OPERATING MODE 6 FAN SPEED 78 TEMPERATURE IN HEX 00213416 (as an example of a valid code) 2 = PanasonicJKE 1 = Power ON 3 = COOL 4 = FAN 4 16 = Temperature 22 degrees (0x16 = 22) */ byte model = (irCommand & 0x00F00000) >> 20; byte power = (irCommand & 0x00010000) >> 16; byte mode = (irCommand & 0x0000F000) >> 12; byte fan = (irCommand & 0x00000F00) >> 8; byte temp = (irCommand & 0x000000FF); const char* buf; Serial.print(F("Model: ")); buf = heatpumpIR[model]->model(); // 'model' is a PROGMEM pointer, so need to write a byte at a time while (char modelChar = pgm_read_byte(buf++)) { Serial.print(modelChar); } Serial.println(); Serial.print(F("Model #: ")); Serial.println(model); Serial.print(F("Power: ")); Serial.println(power); Serial.print(F("Mode: ")); Serial.println(mode); Serial.print(F("Fan: ")); Serial.println(fan); Serial.print(F("Temp: ")); Serial.println(temp); // Heatpump models start from 0, i.e. model number is always less than the number of different models if (model < models) { // This is a supported model // Cancel the timer on Panasonic CKP heatpump if (model == 0) { Serial.println(F("Cancelling timer on Panasonic CKP heatpump...")); timer.stop(panasonicCKPTimer); } Serial.println(F("All OK - sending IR command to heatpump...")); heatpumpIR[model]->send(irSender, power, mode, fan, temp, VDIR_UP, HDIR_AUTO); if (model == 0) { Serial.println(F("Scheduling timer cancellation on Panasonic CKP heatpump...")); panasonicCKPTimer = timer.after(120000, panasonicCancelTimer); // Called after 2 minutes } } } // Cancel the timer on the Panasonic CKP heatpump void panasonicCancelTimer() { PanasonicCKPHeatpumpIR *panasonicCKPHeatpumpIR = new PanasonicCKPHeatpumpIR(); panasonicCKPHeatpumpIR->sendPanasonicCKPCancelTimer(irSender); Serial.println(F("The TIMER led should now be OFF")); }