Skip to content

Instantly share code, notes, and snippets.

@Palantir555
Created July 25, 2024 03:37
Show Gist options
  • Save Palantir555/31a8c431d3213bbd5e09683faca6ea4f to your computer and use it in GitHub Desktop.
Save Palantir555/31a8c431d3213bbd5e09683faca6ea4f to your computer and use it in GitHub Desktop.
/*
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