[Из песочницы] Надежное user-friendly управление силовыми нагрузками умного дома: Domoticz + ручной переключатель

#include 
#include 
#include 
#include 

byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 100, 250};
byte ip[]     = { 192, 168, 100, 199};

// I/O ports on board, 20 for UNO and Leonardo (14 DI + 6 AI) 
static const int ioPorts = 20; 

// all pins                           0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
static const uint8_t arduinoPins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,A0,A1,A2,A3,A4,A5};
static const int availablePin[]    = {1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; //  pins available for general I/O. 1 - available, 0 - not available
static const int domoticz_Idx[]    = {5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //

// Buffers for sending data
char  statusBuffer[ioPorts+1] = "0";           
char  prevStatusBuffer[ioPorts+1] = "0"; 

// Instantiate a Bounce object
Bounce debouncer[ioPorts] = Bounce();

// Function headers
void callback(char* topic, byte* payload, unsigned int length);
char pinToChar(int value);
int compareCharArrays(char  array1[ioPorts+1], char array2[ioPorts+1]);
void readAllPins();
void publishPins(boolean all);
void setup();
void loop();

EthernetClient ethClient;
PubSubClient clientMQTT(server, 1883, callback, ethClient);

void callback(char* topic, byte* payload, unsigned int length) {
  byte* p = (byte*)malloc(length);
  memcpy(p,payload,length);
  publishPins(true); 
  free(p);
}

char pinToChar(int value) {
  char result = 'X';
  if (value==HIGH) {
    result = '0';  // if pin opened, send 0
  }  
  if (value==LOW) {
     result = '1';  // if pin closed to GND, send 1
  }   
  return result; 
}

int compareCharArrays(char  array1[ioPorts+1], char array2[ioPorts+1]) {
  int result = 0;
  for (int i =0; i <= (ioPorts); i++) {
    if (array1[i]!=array2[i]) {
      result = 1;
      break;
    }  
  }  
  return result;    
}

void readAllPins() {
  for (int i =0; i < (ioPorts); i++)
  {
    if (availablePin[i]) 
    {
      debouncer[i].update();
      statusBuffer[i] =  pinToChar(debouncer[i].read());
    }  
  }  
}

void publishPins(boolean all) {
  char topic[]="domoticz/in";
  String data;
  char jsonStr[200];
  for (int i =0; i < (ioPorts); i++)
  {
    if ((all) || (prevStatusBuffer[i]!=statusBuffer[i]))
    {
      if ((availablePin[i]) && (domoticz_Idx[i])) 
      {
        data="{\"idx\":";
        data+=(int)domoticz_Idx[i];
        data+=",\"nvalue\":";
        data+=(char)statusBuffer[i];
        data+="}";
        data.toCharArray(jsonStr,200);
        clientMQTT.publish(topic,jsonStr); 
        Serial.print(topic);
        Serial.print(" ");
        Serial.println(jsonStr);
      }
    }  
  }  
}

void setup() {  
  // initialize serial port over USB  
  Serial.begin(9600);
  
  Ethernet.begin(mac, ip);
  
  // initialize the digital pins as an input.
  for (int i =0; i < ioPorts; i++)
  {
    if (availablePin[i]) { 
      pinMode(i, INPUT_PULLUP);
      debouncer[i].attach(arduinoPins[i]);       // setup the Bounce instance
      debouncer[i].interval(100);   // interval in ms
    }  
    statusBuffer[i]='0';  
    prevStatusBuffer[i]='0'; 
  }
  statusBuffer[ioPorts]='\0';      // EOL
  prevStatusBuffer[ioPorts]='\0';  // EOL

  readAllPins();
  
  if (clientMQTT.connect("myhome-ino-id1")) {
    clientMQTT.subscribe("myhome/ino/id1/in/#");
    publishPins(true);
  }
}

void loop(){
  clientMQTT.loop();
  readAllPins();
  if (compareCharArrays(statusBuffer,prevStatusBuffer)==1)
  // time for send information to the server
  {
      if (!clientMQTT.connected()){
        if (clientMQTT.connect("myhome-ino-id1")) {
          clientMQTT.subscribe("myhome/ino/id1/in/#");
        }  
      } 
      
      if (clientMQTT.connected()) { 
        publishPins(false);
      }  
    
    for (int i =0; i < (ioPorts); i++) {
      prevStatusBuffer[i]=statusBuffer[i]; 
    }
  }    
}


© Geektimes