Created
July 25, 2024 03:37
-
-
Save Palantir555/31a8c431d3213bbd5e09683faca6ea4f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Based on the Matter On/Off Plug-in Unit / Outlet example | |
Modified by JC for old mitsubishi electric HVAC unit using connector CN51 | |
*/ | |
#include <Matter.h> | |
#include <MatterOnOffPluginUnit.h> | |
MatterOnOffPluginUnit matter_outlet; | |
void handle_button_press(); | |
volatile bool button_pressed = false; | |
#define HVAC_SETTER_ONOFF_PIN 12 // 200ms high pulse should toggle hvac on/off | |
#define HVAC_STATUS_ONOFF_PIN 3 | |
#ifndef BTN_BUILTIN | |
#define BTN_BUILTIN PA0 | |
#endif | |
#define SUPPORT_DECOMMISSION | |
bool read_hvac_onoff_state() | |
{ | |
return digitalRead(HVAC_STATUS_ONOFF_PIN) ? false : true; // off==high | |
} | |
void write_hvac_onoff_state(bool on) | |
{ | |
if (read_hvac_onoff_state() != on) | |
{ | |
Serial.println("[LOG] Virtually pressing ON/OFF button"); | |
digitalWrite(HVAC_SETTER_ONOFF_PIN, HIGH); | |
delay(250); | |
digitalWrite(HVAC_SETTER_ONOFF_PIN, LOW); | |
delay(250); | |
if (read_hvac_onoff_state() != on) { | |
Serial.println("\t[ERR] Controller did not react to button press"); | |
} else { | |
Serial.println("\t[OK]"); | |
} | |
} | |
//matter_outlet.set_onoff(on); | |
} | |
void setup() | |
{ | |
// Set up the pins used to hook into the HVAC's controller | |
pinMode(HVAC_SETTER_ONOFF_PIN, OUTPUT); | |
digitalWrite(HVAC_SETTER_ONOFF_PIN, LOW); | |
pinMode(HVAC_STATUS_ONOFF_PIN, INPUT_PULLUP); | |
Serial.begin(115200); | |
Matter.begin(); | |
matter_outlet.begin(); | |
// Set up the onboard LED | |
pinMode(LED_BUILTIN, OUTPUT); | |
digitalWrite(LED_BUILTIN, LED_BUILTIN_INACTIVE); | |
// Set up the onboard button | |
pinMode(BTN_BUILTIN, INPUT_PULLUP); | |
attachInterrupt(BTN_BUILTIN, &handle_button_press, FALLING); | |
Serial.println("Matter On/Off Plug-in Unit / Outlet"); | |
do { // In case device is decomm'd here | |
if (!Matter.isDeviceCommissioned()) { | |
Serial.println("Matter device is not commissioned"); | |
Serial.println("Commission it to your Matter hub with the manual " | |
"pairing code or QR code"); | |
Serial.printf("Manual pairing code: %s\n", Matter.getManualPairingCode().c_str()); | |
Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str()); | |
} | |
while (!Matter.isDeviceCommissioned()) { | |
delay(500); | |
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); | |
} | |
Serial.println("Waiting for Thread network..."); | |
while (!Matter.isDeviceThreadConnected()) { | |
delay(300); | |
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); | |
#ifdef SUPPORT_DECOMMISSION | |
if (button_pressed) { | |
decommissionHandler(); | |
break; | |
} | |
#endif | |
} | |
if (!Matter.isDeviceCommissioned()) { | |
continue; | |
} | |
Serial.println("Connected to Thread network"); | |
Serial.println("Waiting for Matter device discovery..."); | |
while (!matter_outlet.is_online()) { | |
delay(100); | |
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); | |
#ifdef SUPPORT_DECOMMISSION | |
if (button_pressed) { | |
decommissionHandler(); | |
break; | |
} | |
#endif | |
} | |
} while (!Matter.isDeviceCommissioned()); | |
digitalWrite(LED_BUILTIN, LED_BUILTIN_ACTIVE); | |
Serial.println("Matter device is now online"); | |
bool initial_state = read_hvac_onoff_state(); | |
matter_outlet.set_onoff(initial_state); | |
} | |
void loop() | |
{ | |
static bool matter_outlet_last_state = read_hvac_onoff_state(); | |
bool matter_outlet_current_state = matter_outlet.get_onoff(); | |
// If the current state is ON and the previous was OFF - turn on the LED | |
if (matter_outlet_current_state && !matter_outlet_last_state) { | |
matter_outlet_last_state = matter_outlet_current_state; | |
write_hvac_onoff_state(true); | |
digitalWrite(LED_BUILTIN, LED_BUILTIN_ACTIVE); | |
} | |
// If the current state is OFF and the previous was ON - turn off the LED | |
if (!matter_outlet_current_state && matter_outlet_last_state) { | |
matter_outlet_last_state = matter_outlet_current_state; | |
write_hvac_onoff_state(false); | |
digitalWrite(LED_BUILTIN, LED_BUILTIN_INACTIVE); | |
} | |
// If the hvac controller's LED changed by itself, it must have been physically toggled | |
if (read_hvac_onoff_state() != matter_outlet_current_state) { | |
Serial.println("[Physical] HVAC state changed"); | |
matter_outlet.set_onoff(read_hvac_onoff_state()); // toggle() should suffice | |
// Will be acted on by the next iteration | |
} | |
if (button_pressed) { | |
button_pressed = false; | |
Serial.println("[Physical] Button pressed"); | |
#if defined(SUPPORT_DECOMMISSION) | |
decommissionHandler(); | |
// TODO: Should restart the device here... | |
#else | |
// Debug code: If the arduino's button was pressed, toggle the HVAC | |
matter_outlet.toggle(); | |
#endif | |
} | |
} | |
#if defined(SUPPORT_DECOMMISSION) | |
void decommissionHandler() { | |
button_pressed = false; // handled button press event | |
if (digitalRead(BTN_BUILTIN) == HIGH) { | |
return; // push button not pressed | |
} | |
// measures time pressed | |
int startTime = millis(); | |
while (digitalRead(BTN_BUILTIN) == LOW) { | |
int elapsedTime = (millis() - startTime) / 1000.0; | |
if (elapsedTime < 10) { | |
delay(50); | |
continue; // Waiting for 10 seconds | |
} | |
Serial.println("[LOG] Decommissioning...\n"); | |
for (int i = 0; i < 10; i++) { | |
digitalWrite(LED_BUILTIN, !(digitalRead(LED_BUILTIN))); | |
delay(100); | |
}; | |
if (!Matter.isDeviceCommissioned()) { | |
Serial.println("\t[OK] Decommission done!"); | |
digitalWrite(LED_BUILTIN, LOW); | |
} else { | |
Serial.println("\tMatter device is commissioned-> " | |
"Starting Decommission process"); | |
nvm3_eraseAll(nvm3_defaultHandle); // Decomission command | |
digitalWrite(LED_BUILTIN, LOW); | |
Serial.println("\t[OK] Decommission done!"); | |
} | |
break; | |
} | |
} | |
#endif | |
void handle_button_press() | |
{ | |
const int DEBOUNCE_TIME = 200; // 200ms ; debounce | |
static uint32_t btn_last_press = 0u; | |
if (millis() < btn_last_press + DEBOUNCE_TIME) { | |
return; | |
} | |
btn_last_press = millis(); | |
button_pressed = true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment