Wrapping up the message parsing system

We have added new sensors to the Smart Home application. In order to handle all incoming messages correctly, we need to be able to parse messages correctly to inform the user. When we added new command classes, we needed to handle their values separately. A part of the message parser, which handles sensor commands, is shown here. We also used a part of this in the previous chapter to handle energy meter values such as illumination and temperature:

int parse_incoming_mesage(uint8_t* message, int length) {
//Message Length
  uint8_t length_of_rest = message[1];
  uint8_t message_type = message[2];
  uint8_t message_function = message[3];
   
   else if (message_function == RESPONSE_RECEIVED) {
    printf("Response From ");
    if (message[5] == MultiSensorNodeID) {
      printf("Multi-Sensor Node Received: ");
    } else if (message[5] == WallPlugNodeID) {
      printf("Wall Plug Node Received: ");
    } else if (message[5] == LampHolderNodeID) {
      printf("Lamp Holder Node Received: ");
    } else if (message[5] == FloodSensorNodeID) {
      printf("Flood Sensor Node Received: ");
    }
    //Length of Data
    uint8_t data_length = message[6];
    uint8_t command_class = message[7];
    
    //Check Command Class and Take Action Accordingly
    if (command_class == COMMAND_CLASS_BATTERY) {
      int battery = 0;
      //If battery is not 0%
      if (message[9] != 0xFF) {
        battery = message[9];
      }
      if (message[5] == MultiSensorNodeID) {
        multi_sensor_battery_level = battery;
      } else if (message[5] == FloodSensorNodeID) {
        flood_sensor_battery_level = battery;
      }
      printf("Battery Level of Device is %d % 
", battery);
    } else if (command_class == COMMAND_CLASS_SENSOR_BINARY) {
      if (message[8] == BINARY_REPORT) {
        if (data_length == 0x04) {
          if (message[10] == DOOR_WINDOW_SENSOR) {
            if (message[9] == ON) {
              printf("Door/Window Sensor is OPEN
");
              door_sensor_status = message[9];
            } else if (message[9] == OFF) {
              printf("Door/Window Sensor is CLOSE
");
              door_sensor_status = message[9];
            }
          } else if (message[10] == MOTION_DETECTION_SENSOR) {
            if (message[9] == ON) {
              printf("Motion DETECTED
");
              motion_sensor_status = message[9];
            } else if (message[9] == OFF) {
              printf("NO Motion Detected
");
              motion_sensor_status = message[9];  }    }}
    
} else if (command_class == COMMAND_CLASS_SENSOR_MULTILEVEL_V2) {
      if (message[8] == MULTILEVEL_REPORT) {
         // Calculate Sensor Value
        int len = data_length - 3;
        uint8_t *data = malloc(len * sizeof(uint8_t));
        uint8_t scale;
        int i = 0;
        for (; i < len; i++) {
          data[i] = message[10 + i];
        }
        float value = calculate_sensor_value(data, len, &scale);
        if (message[9] == TEMPERATURE_SENSOR) {
          printf("Temperature Value is %f ", value);
          temperature = value;
          if (scale) {
            printf("Fahrenheit 
");
          } else {
            printf("Celcius 
");
          }
        } else if (message[9] == LUMINANCE_SENSOR) {
          printf("Illumination is %f ", value);
          illumination = value;
          if (scale) {
            printf("Lux 
");
          } else {
            printf("% 
");
          }
        } else if (message[9] == POWER_SENSOR) {
          printf("Power Value is %f 
", value);
          current_energy_consumption = value;
          if (scale) {
            printf("BUT/h 
");
          } else {
            printf("Watts 
");
          }
        }
      }
    } else if (command_class == COMMAND_CLASS_BASIC) {
      printf("Device is ");
      if (message[9] == OFF) {
        printf("Sleeping
");
      } else if (message[9] == ON) {
        printf("Active
");
      }
      if (message[5] == WallPlugNodeID) {
        wall_plug_status = message[9];
      } else if (message[5] == MultiSensorNodeID) {
        multi_sensor_status = message[9];
      } else if (message[5] == LampHolderNodeID) {
        lamp_holder_status = message[9];
      } else if (message[5] == FloodSensorNodeID) {
        flood_detector_status = message[9];
      }
    } 
……//some code here…………
………………….
    } else if (command_class == COMMAND_CLASS_METER) {
      //Open ZWave Meter
      int len = data_length - 3;
      uint8_t *data = malloc(len * sizeof(uint8_t));
      uint8_t scale;
      int i = 0;
      for (; i < len; i++) {
        data[i] = message[10 + i];
      }
      float value = calculate_sensor_value(data, len, &scale);
      if (message[8] == METER_REPORT) {
        uint8_t meter_type = message[9] & 0x1F;
        if (meter_type == METER_ELECTRICITY) {
          const char* label = electricity_label_names[scale];
          const char* unit = electricity_unit_names[scale];
          printf("Electicity Meter Report %s %f %s
", label, value, unit);
          if (scale == 2) {
            current_energy_consumption = value;
          } else if (scale == 0) {
            cumulative_energy_level = value;
          }
        } 
      }
    } else if (command_class == COMMAND_CLASS_SENSOR_ALARM) {
      printf("Sensor Alarm ");
      if (message[8] == SENSOR_ALARM_REPORT) {
        printf("Reported ");
        if (message[10] == FLOOD_ALARM) {
          if (message[11] == ON) {
            printf("FLOOD Detected
");
          } else if (message[11] == OFF) {
            printf("NO Flood Danger
");
          }
          flood_sensor_status = message[11];
        } else if (message[10] == SMOKE_ALARM) {
          if (message[11] == ON) {
            printf("SMOKE Detected
");
          } else if (message[11] == OFF) {
            printf("NO Fire Danger
");
          }}}}}
  return 0;
}

We have also added a new command function to request an alarm sensor status. get_sensor_alarm_value makes the request to the corresponding alarm sensor to get its latest status:

 int get_sensor_alarm_value(int serial_device, uint8_t nodeID, uint8_t sensor_type, uint8_t callbackID) {
  int message_length = 12;
  uint8_t checksum = 0x00;
  uint8_t message_buffer[] = { SOF, (message_length - 2), REQUEST, SEND_DATA,
      nodeID, 0x03, COMMAND_CLASS_SENSOR_ALARM, SENSOR_ALARM_GET, sensor_type,
      TRANSMIT_OPTION, callbackID, checksum };
  checksum = generate_checksum(message_buffer, message_length);
  message_buffer[message_length - 1] = checksum;
  return write_to_serial_device(serial_device, message_buffer, message_length);
}

As can be seen in the message parser function, when a sensor value or device status is received, it sets a static variable value, that will help us in the following chapter to monitor the current situation of the area. In order to monitor sensors and send them messages, a synchronous mechanism needs to be implemented carefully so as to not miss any messages from the controller.

In the next chapter, while we are in the process of improving our sample application, we will add a thread lock mechanism to use the Z-Wave USB adapter safely with multiple threads. That will help us monitor, send messages, and receive messages in a more secure way.

With the latest code samples, we will get experience at handling Z-Wave messages. This will help you to understand how complex it gets when the number of devices and cases increases, and so every case should be handled carefully, especially security cases; in real life scenarios, not doing so can cause damage in your home or any other residential areas where home automation has been setup.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset