diff options
Diffstat (limited to 'epan/dissectors')
-rw-r--r-- | epan/dissectors/packet-zbee-zcl-general.c | 1901 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-zcl.c | 36 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-zcl.h | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee.h | 2 |
4 files changed, 1908 insertions, 32 deletions
diff --git a/epan/dissectors/packet-zbee-zcl-general.c b/epan/dissectors/packet-zbee-zcl-general.c index 2fb1307bbc..0b1c58cdee 100644 --- a/epan/dissectors/packet-zbee-zcl-general.c +++ b/epan/dissectors/packet-zbee-zcl-general.c @@ -267,12 +267,12 @@ dissect_zcl_basic_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guin case ZBEE_ZCL_ATTR_ID_BASIC_POWER_SOURCE: proto_tree_add_item(tree, hf_zbee_zcl_basic_pwr_src, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; break; case ZBEE_ZCL_ATTR_ID_BASIC_DEVICE_ENABLED: proto_tree_add_item(tree, hf_zbee_zcl_basic_dev_en, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; break; case ZBEE_ZCL_ATTR_ID_BASIC_ALARM_MASK: @@ -282,7 +282,7 @@ dissect_zcl_basic_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guin proto_tree_add_item(sub_tree, hf_zbee_zcl_basic_alarm_mask_gen_hw_fault, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_basic_alarm_mask_gen_sw_fault, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_basic_alarm_mask_reserved, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; break; case ZBEE_ZCL_ATTR_ID_BASIC_DISABLE_LOCAL_CFG: @@ -292,7 +292,7 @@ dissect_zcl_basic_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guin proto_tree_add_item(sub_tree, hf_zbee_zcl_basic_disable_local_cfg_reset, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_basic_disable_local_cfg_device_cfg, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_basic_disable_local_cfg_reserved, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; break; case ZBEE_ZCL_ATTR_ID_BASIC_ZCL_VERSION: @@ -595,7 +595,7 @@ dissect_zcl_identify_identify(tvbuff_t *tvb, proto_tree *tree, guint *offset) { /* Retrieve "Identify Time" field */ proto_tree_add_item(tree, hf_zbee_zcl_identify_identify_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN); - *offset += (int)2; + *offset += 2; } /*dissect_zcl_identify_identify*/ @@ -618,7 +618,7 @@ dissect_zcl_identify_identifyqueryrsp(tvbuff_t *tvb, proto_tree *tree, guint *of { /* Retrieve "Identify Timeout" field */ proto_tree_add_item(tree, hf_zbee_zcl_identify_identify_timeout, tvb, *offset, 2, ENC_LITTLE_ENDIAN); - *offset += (int)2; + *offset += 2; } /*dissect_zcl_identify_identifyqueryrsp*/ @@ -670,7 +670,7 @@ dissect_zcl_identify_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, g case ZBEE_ZCL_ATTR_ID_IDENTIFY_IDENTIFY_TIME: proto_tree_add_item(tree, hf_zbee_zcl_identify_identify_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN); - *offset += (int)2; + *offset += 2; break; default: @@ -911,7 +911,7 @@ dissect_zcl_on_off_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, gui case ZBEE_ZCL_ON_OFF_ATTR_ID_ONOFF: proto_tree_add_item(tree, hf_zbee_zcl_on_off_attr_onoff, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; break; default: @@ -1240,7 +1240,7 @@ static void dissect_zcl_part_trasfpartframe(tvbuff_t *tvb, proto_tree *tree, gui proto_tree_add_item(sub_tree, hf_zbee_zcl_part_opt_first_block, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_part_opt_indic_len, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_part_opt_res, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; /* Retrieve "PartitionIndicator" field */ if ((options & ZBEE_ZCL_PART_OPT_INDIC_LEN) == 0) @@ -1248,25 +1248,25 @@ static void dissect_zcl_part_trasfpartframe(tvbuff_t *tvb, proto_tree *tree, gui /* 1-byte length */ u16len = (guint16)tvb_get_guint8(tvb, *offset); proto_tree_add_item(tree, hf_zbee_zcl_part_part_indicator, tvb, *offset, 1, (u16len & 0xFF)); - *offset += (int)1; + *offset += 1; } else { /* 2-bytes length */ u16len = tvb_get_letohs(tvb, *offset); proto_tree_add_item(tree, hf_zbee_zcl_part_part_indicator, tvb, *offset, 2, u16len); - *offset += (int)2; + *offset += 2; } /* Retrieve PartitionedFrame length field */ frame_len = tvb_get_guint8(tvb, *offset); /* string length */ if (frame_len == ZBEE_ZCL_INVALID_STR_LENGTH) frame_len = 0; proto_tree_add_item(tree, hf_zbee_zcl_part_part_frame_len, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; /* Retrieve "PartitionedFrame" field */ data_frame = tvb_bytes_to_str_punct(tvb, *offset, frame_len, ':'); proto_tree_add_string(tree, hf_zbee_zcl_part_part_frame, tvb, *offset, frame_len, data_frame); - *offset += frame_len; + *offset += (int)frame_len; } /*dissect_zcl_part_trasfpartframe*/ @@ -1291,7 +1291,7 @@ dissect_zcl_part_rdhandshakeparam(tvbuff_t *tvb, proto_tree *tree, guint *offset /* Retrieve "Partitioned Cluster ID" field */ proto_tree_add_item(tree, hf_zbee_zcl_part_partitioned_cluster_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN); - *offset += (int)2; + *offset += 2; /* Dissect the attribute id list */ tvb_len = tvb_length(tvb); @@ -1299,7 +1299,7 @@ dissect_zcl_part_rdhandshakeparam(tvbuff_t *tvb, proto_tree *tree, guint *offset /* Dissect the attribute identifier */ attr_id = tvb_get_letohs(tvb, *offset); dissect_zcl_part_attr_id(tree, tvb, offset, attr_id); - *offset += (int)2; + *offset += 2; } return; @@ -1325,7 +1325,7 @@ dissect_zcl_part_wrhandshakeparam(tvbuff_t *tvb, packet_info *pinfo, proto_tree { /* Retrieve "Partitioned Cluster ID" field */ proto_tree_add_item(tree, hf_zbee_zcl_part_partitioned_cluster_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN); - *offset += (int)2; + *offset += 2; /* Dissect the attributes list */ dissect_zcl_write_attr(tvb, pinfo, tree, offset); @@ -1367,7 +1367,7 @@ dissect_zcl_part_multiack(tvbuff_t *tvb, proto_tree *tree, guint *offset) sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_part_ack_opts); proto_tree_add_item(sub_tree, hf_zbee_zcl_part_ack_opt_nack_id_len, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_zbee_zcl_part_ack_opt_res, tvb, *offset, 1, ENC_NA); - *offset += (int)1; + *offset += 1; /* Retrieve "First Frame ID" field */ if ((options & ZBEE_ZCL_PART_ACK_OPT_NACK_LEN) == 0) @@ -1375,13 +1375,13 @@ dissect_zcl_part_multiack(tvbuff_t *tvb, proto_tree *tree, guint *offset) /* 1-byte length */ first_frame_id = (guint16)tvb_get_guint8(tvb, *offset); proto_tree_add_item(tree, hf_zbee_zcl_part_first_frame_id, tvb, *offset, 1, (first_frame_id & 0xFF)); - *offset += (int)1; + *offset += 1; } else { /* 2-bytes length */ first_frame_id = tvb_get_letohs(tvb, *offset); proto_tree_add_item(tree, hf_zbee_zcl_part_first_frame_id, tvb, *offset, 2, first_frame_id); - *offset += (int)2; + *offset += 2; } /* Dissect the nack id list */ @@ -1392,13 +1392,13 @@ dissect_zcl_part_multiack(tvbuff_t *tvb, proto_tree *tree, guint *offset) /* 1-byte length */ nack_id = (guint16)tvb_get_guint8(tvb, *offset); proto_tree_add_item(tree, hf_zbee_zcl_part_nack_id, tvb, *offset, 1, (nack_id & 0xFF)); - *offset += (int)1; + *offset += 1; } else { /* 2-bytes length */ nack_id = tvb_get_letohs(tvb, *offset); proto_tree_add_item(tree, hf_zbee_zcl_part_nack_id, tvb, *offset, 2, nack_id); - *offset += (int)2; + *offset += 2; } i++; @@ -1424,7 +1424,7 @@ dissect_zcl_part_rdhandshakeparamrsp(tvbuff_t *tvb, packet_info *pinfo, proto_tr { /* Retrieve "Partitioned Cluster ID" field */ proto_tree_add_item(tree, hf_zbee_zcl_part_partitioned_cluster_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN); - *offset += (int)2; + *offset += 2; /* Dissect the attributes list */ dissect_zcl_read_attr_resp(tvb, pinfo, tree, offset); @@ -1591,3 +1591,1860 @@ void proto_reg_handoff_zbee_zcl_part(void) } /*proto_reg_handoff_zbee_zcl_part*/ + +/* ########################################################################## */ +/* #### (0x001A) POWER PROFILE CLUSTER ###################################### */ +/* ########################################################################## */ + +/*************************/ +/* Defines */ +/*************************/ + +#define ZBEE_ZCL_PWR_PROF_NUM_GENERIC_ETT 4 +#define ZBEE_ZCL_PWR_PROF_NUM_PWR_PROF_ETT 5 +#define ZBEE_ZCL_PWR_PROF_NUM_EN_PHS_ETT 16 +#define ZBEE_ZCL_PWR_PROF_NUM_ETT (ZBEE_ZCL_PWR_PROF_NUM_GENERIC_ETT + \ + ZBEE_ZCL_PWR_PROF_NUM_PWR_PROF_ETT + \ + ZBEE_ZCL_PWR_PROF_NUM_EN_PHS_ETT) + +/* Attributes */ +#define ZBEE_ZCL_ATTR_ID_PWR_PROF_TOT_PROF_NUM 0x0000 /* Total Profile Number */ +#define ZBEE_ZCL_ATTR_ID_PWR_PROF_MULTIPLE_SCHED 0x0001 /* Multiple Schedule */ +#define ZBEE_ZCL_ATTR_ID_PWR_PROF_ENERGY_FORMAT 0x0002 /* Energy Formatting */ +#define ZBEE_ZCL_ATTR_ID_PWR_PROF_ENERGY_REMOTE 0x0003 /* Energy Remote */ +#define ZBEE_ZCL_ATTR_ID_PWR_PROF_SCHED_MODE 0x0004 /* Schedule Mode */ + +/* Server Commands Received */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_REQ 0x00 /* Power Profile Request */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_REQ 0x01 /* Power Profile State Request */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_RSP 0x02 /* Get Power Profile Price Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_GET_OVERALL_SCHED_PRICE_RSP 0x03 /* Get Overall Schedule Price Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_NOTIF 0x04 /* Energy Phases Schedule Notification */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_RSP 0x05 /* Energy Phases Schedule Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_REQ 0x06 /* Power Profile Schedule Constraints Request */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_REQ 0x07 /* Energy Phases Schedule State Request */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_EXT_RSP 0x08 /* Get Power Profile Price Extended Response */ + +/* Server Commands Generated */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_NOTIF 0x00 /* Power Profile Notification */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_RSP 0x01 /* Power Profile Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_RSP 0x02 /* Power Profile State Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE 0x03 /* Get Power Profile Price */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_NOTIF 0x04 /* Power Profile State Notification */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_GET_OVERALL_SCHED_PRICE 0x05 /* Get Overall Schedule Price */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_REQ 0x06 /* Energy Phases Schedule Request */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_RSP 0x07 /* Energy Phases Schedule State Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_NOITIF 0x08 /* Energy Phases Schedule State Notification */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_NOTIF 0x09 /* Power Profile Schedule Constraints Notification */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_RSP 0x0A /* Power Profile Schedule Constraints Response */ +#define ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_EXT 0x0B /* Get Power Profile Price Extended */ + +/* Power Profile StateId */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_PWR_PROF_IDLE 0x00 /* Power Profile Idle */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_PWR_PROF_PROGRAMMED 0x01 /* Power Profile Programmed */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_RUNNING 0x03 /* Energy Phase Running */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_PAUSE 0x04 /* Energy Phase Pause */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_WAITING_TO_START 0x05 /* Energy Phase Waiting to Start */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_WAITING_PAUSED 0x06 /* Energy Phase Waiting Pause */ +#define ZBEE_ZCL_PWR_PROF_STATE_ID_PWR_PROF_ENDED 0x07 /* Power Profile Ended */ + +/* Energy Formatting bitmask field list */ +#define ZBEE_ZCL_OPT_PWRPROF_NUM_R_DIGIT 0x07 /* bits 0..2 */ +#define ZBEE_ZCL_OPT_PWRPROF_NUM_L_DIGIT 0x78 /* bits 3..6 */ +#define ZBEE_ZCL_OPT_PWRPROF_NO_LEADING_ZERO 0x80 /* bit 7 */ + +/* Schedule Mode bitmask field list */ +#define ZBEE_ZCL_OPT_PWRPROF_SCHED_CHEAPEST 0x01 /* bit 0 */ +#define ZBEE_ZCL_OPT_PWRPROF_SCHED_GREENEST 0x02 /* bit 1 */ +#define ZBEE_ZCL_OPT_PWRPROF_SCHED_RESERVED 0xfc /* bits 2..7 */ + +/* Options bitmask field list */ +#define ZBEE_ZCL_OPT_PWRPROF_STIME_PRESENT 0x01 /* bit 0 */ +#define ZBEE_ZCL_OPT_PWRPROF_RESERVED 0xfe /* bits 1..7 */ + +/*************************/ +/* Function Declarations */ +/*************************/ + +/* Command Dissector Helpers */ +static void dissect_zcl_pwr_prof_pwrprofreq (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_getpwrprofpricersp (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_getoverallschedpricersp (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_enphsschednotif (tvbuff_t *tvb, proto_tree *tree, guint *offset); + +static void dissect_zcl_energy_phase (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_pwrprofnotif (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_power_profile (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_pwrprofstatersp (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_pwrprofschedcontrsnotif (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_pwr_prof_pwrprofpriceext (tvbuff_t *tvb, proto_tree *tree, guint *offset); + +/* Private functions prototype */ +static void dissect_zcl_pwr_prof_attr_id (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id); +static void dissect_zcl_pwr_prof_attr_data (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type); + +static void decode_power_profile_id (gchar *s, guint8 id); +static void decode_price_in_cents (gchar *s, guint32 value); +static void decode_power_in_watt (gchar *s, guint16 value); +static void decode_energy (gchar *s, guint16 value); + +/*************************/ +/* Global Variables */ +/*************************/ +/* Initialize the protocol and registered fields */ +static int proto_zbee_zcl_pwr_prof = -1; + +static int hf_zbee_zcl_pwr_prof_attr_id = -1; +static int hf_zbee_zcl_pwr_prof_tot_prof_num = -1; +static int hf_zbee_zcl_pwr_prof_multiple_sched = -1; +static int hf_zbee_zcl_pwr_prof_energy_format_rdigit = -1; +static int hf_zbee_zcl_pwr_prof_energy_format_ldigit = -1; +static int hf_zbee_zcl_pwr_prof_energy_format_noleadingzero = -1; +static int hf_zbee_zcl_pwr_prof_energy_remote = -1; +static int hf_zbee_zcl_pwr_prof_sched_mode_cheapest = -1; +static int hf_zbee_zcl_pwr_prof_sched_mode_greenest = -1; +static int hf_zbee_zcl_pwr_prof_sched_mode_reserved = -1; +static int hf_zbee_zcl_pwr_prof_srv_tx_cmd_id = -1; +static int hf_zbee_zcl_pwr_prof_srv_rx_cmd_id = -1; +static int hf_zbee_zcl_pwr_prof_pwr_prof_id = -1; +static int hf_zbee_zcl_pwr_prof_currency = -1; +static int hf_zbee_zcl_pwr_prof_price = -1; +static int hf_zbee_zcl_pwr_prof_price_trailing_digit = -1; +static int hf_zbee_zcl_pwr_prof_num_of_sched_phases = -1; +static int hf_zbee_zcl_pwr_prof_scheduled_time = -1; +static int hf_zbee_zcl_pwr_prof_pwr_prof_count = -1; +static int hf_zbee_zcl_pwr_prof_num_of_trans_phases = -1; +static int hf_zbee_zcl_pwr_prof_energy_phase_id = -1; +static int hf_zbee_zcl_pwr_prof_macro_phase_id = -1; +static int hf_zbee_zcl_pwr_prof_expect_duration = -1; +static int hf_zbee_zcl_pwr_prof_peak_power = -1; +static int hf_zbee_zcl_pwr_prof_energy = -1; +static int hf_zbee_zcl_pwr_prof_max_active_delay = -1; +static int hf_zbee_zcl_pwr_prof_pwr_prof_rem_ctrl = -1; +static int hf_zbee_zcl_pwr_prof_pwr_prof_state = -1; +static int hf_zbee_zcl_pwr_prof_start_after = -1; +static int hf_zbee_zcl_pwr_prof_stop_before = -1; +static int hf_zbee_zcl_pwr_prof_options_01 = -1; +static int hf_zbee_zcl_pwr_prof_options_res = -1; +static int hf_zbee_zcl_pwr_prof_pwr_prof_stime = -1; + +/* Initialize the subtree pointers */ +static gint ett_zbee_zcl_pwr_prof = -1; +static gint ett_zbee_zcl_pwr_prof_options = -1; +static gint ett_zbee_zcl_pwr_prof_en_format = -1; +static gint ett_zbee_zcl_pwr_prof_sched_mode = -1; +static gint ett_zbee_zcl_pwr_prof_pwrprofiles[ZBEE_ZCL_PWR_PROF_NUM_PWR_PROF_ETT]; +static gint ett_zbee_zcl_pwr_prof_enphases[ZBEE_ZCL_PWR_PROF_NUM_EN_PHS_ETT]; + +/* Attributes */ +static const value_string zbee_zcl_pwr_prof_attr_names[] = { + { ZBEE_ZCL_ATTR_ID_PWR_PROF_TOT_PROF_NUM, "Total Profile Number" }, + { ZBEE_ZCL_ATTR_ID_PWR_PROF_MULTIPLE_SCHED, "Multiple Scheduling" }, + { ZBEE_ZCL_ATTR_ID_PWR_PROF_ENERGY_FORMAT, "Energy Formatting" }, + { ZBEE_ZCL_ATTR_ID_PWR_PROF_ENERGY_REMOTE, "Energy Remote" }, + { ZBEE_ZCL_ATTR_ID_PWR_PROF_SCHED_MODE, "Schedule Mode" }, + { 0, NULL } +}; + +/* Server Commands Received */ +static const value_string zbee_zcl_pwr_prof_srv_rx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_REQ, "Power Profile Request" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_REQ, "Power Profile State Request" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_RSP, "Get Power Profile Price Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_GET_OVERALL_SCHED_PRICE_RSP, "Get Overall Schedule Price Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_NOTIF, "Energy Phases Schedule Notification" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_RSP, "Energy Phases Schedule Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_REQ, "Power Profile Schedule Constraints Request" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_REQ, "Energy Phases Schedule State Request" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_EXT_RSP, "Get Power Profile Price Extended Response" }, + { 0, NULL } +}; + +/* Server Commands Generated */ +static const value_string zbee_zcl_pwr_prof_srv_tx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_NOTIF, "Power Profile Notification" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_RSP, "Power Profile Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_RSP, "Power Profile State Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE, "Get Power Profile Price" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_NOTIF, "Power Profile State Notification" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_GET_OVERALL_SCHED_PRICE, "Get Overall Schedule Price" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_REQ, "Energy Phases Schedule Request" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_RSP, "Energy Phases Schedule State Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_NOITIF, "Energy Phases Schedule State Notification" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_NOTIF, "Power Profile Schedule Constraints Notification" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_RSP, "Power Profile Schedule Constraints Response" }, + { ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_EXT, "Get Power Profile Price Extended" }, + { 0, NULL } +}; + +/* Currencies (values defined by ISO 4217) */ +static const value_string zbee_zcl_currecy_names[] = { + { 0x03D2, "EUR" }, + { 0x033A, "GBP" }, + { 0x0348, "USD" }, + { 0, NULL } +}; + +/* Power Profile State */ +static const value_string zbee_zcl_pwr_prof_state_names[] = { + { ZBEE_ZCL_PWR_PROF_STATE_ID_PWR_PROF_IDLE, "Power Profile Idle" }, + { ZBEE_ZCL_PWR_PROF_STATE_ID_PWR_PROF_PROGRAMMED, "Power Profile Programmed" }, + { ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_RUNNING, "Energy Phase Running" }, + { ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_PAUSE, "Energy Phase Pause" }, + { ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_WAITING_TO_START, "Energy Phase Waiting to Start" }, + { ZBEE_ZCL_PWR_PROF_STATE_ID_EN_PH_WAITING_PAUSED, "Energy Phase Waiting Paused" }, + { ZBEE_ZCL_PWR_PROF_STATE_ID_PWR_PROF_ENDED, "Power Profile Ended" }, + { 0, NULL } +}; + +/* Options Names */ +static const value_string zbee_zcl_options_types[] = { + { ZBEE_ZCL_OPT_PWRPROF_STIME_PRESENT, "PowerProfileStartTime Field Present" }, + { 0, NULL } +}; + +/*************************/ +/* Function Bodies */ +/*************************/ + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zbee_zcl_pwr_prof + * DESCRIPTION + * ZigBee ZCL Power Profile cluster dissector for wireshark. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * packet_info *pinfo - pointer to packet information fields + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zbee_zcl_pwr_prof (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *payload_root = NULL; + proto_tree *payload_tree = NULL; + zbee_zcl_packet *zcl = (zbee_zcl_packet *)pinfo->private_data; + guint offset = 0; + guint8 cmd_id = zcl->cmd_id; + + /* Create a subtree for the ZCL Command frame, and add the command ID to it. */ + if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { + if (tree) { + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_srv_rx_cmd_id, tvb, offset, 1, cmd_id); + /* Check is this command has a payload, than add the payload tree */ + if (offset != (tvb_length(tvb) - 1)) { + payload_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Payload"); + payload_tree = proto_item_add_subtree(payload_root, ett_zbee_zcl_pwr_prof); + } + } + offset += 1; + + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_pwr_prof_srv_rx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Call the appropriate command dissector */ + switch (cmd_id) { + + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_REQ: + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_REQ: + case ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_REQ: + dissect_zcl_pwr_prof_pwrprofreq(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_REQ: + /* No payload */ + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_RSP: + case ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_EXT_RSP: + dissect_zcl_pwr_prof_getpwrprofpricersp(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_GET_OVERALL_SCHED_PRICE_RSP: + dissect_zcl_pwr_prof_getoverallschedpricersp(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_NOTIF: + case ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_RSP: + dissect_zcl_pwr_prof_enphsschednotif(tvb, payload_tree, &offset); + break; + + default: + break; + } + } + else { /* ZBEE_ZCL_FCF_TO_CLIENT */ + + if (tree) { + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_srv_tx_cmd_id, tvb, offset, 1, cmd_id); + /* Check is this command has a payload, than add the payload tree */ + if (offset != (tvb_length(tvb) - 1)) { + payload_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Payload"); + payload_tree = proto_item_add_subtree(payload_root, ett_zbee_zcl_pwr_prof); + } + } + offset += 1; + + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_pwr_prof_srv_tx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Call the appropriate command dissector */ + switch (cmd_id) { + + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_NOTIF: + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_RSP: + dissect_zcl_pwr_prof_pwrprofnotif(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_RSP: + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_STATE_NOTIF: + dissect_zcl_pwr_prof_pwrprofstatersp(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_GET_OVERALL_SCHED_PRICE: + /* no payload */ + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_RSP: + case ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_STATE_NOITIF: + dissect_zcl_pwr_prof_enphsschednotif(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE: + case ZBEE_ZCL_CMD_ID_PWR_PROF_ENERGY_PHASES_SCHED_REQ: + dissect_zcl_pwr_prof_pwrprofreq(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_NOTIF: + case ZBEE_ZCL_CMD_ID_PWR_PROF_PWR_PROF_SCHED_CONSTRS_RSP: + dissect_zcl_pwr_prof_pwrprofschedcontrsnotif(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_PWR_PROF_GET_PWR_PROF_PRICE_EXT: + dissect_zcl_pwr_prof_pwrprofpriceext(tvb, payload_tree, &offset); + break; + + default: + break; + } + } +} /*dissect_zbee_zcl_pwr_prof*/ + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_pwrprofreq + * DESCRIPTION + * this function is called in order to decode "PowerProfileRequest", + * "PowerProfileScheduleConstraintsRequest", "EnergyPhasesScheduleStateRequest", + * "GetPowerProfilePrice" and "EnergyPhasesScheduleRequest" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_pwrprofreq(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Retrieve "Power Profile Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + +} /*dissect_zcl_pwr_prof_pwrprofreq*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_getpwrprofpricersp + * DESCRIPTION + * this function is called in order to decode "GetPowerProfilePriceResponse" + * and "PowerProfilePriceExtendedResponse" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_getpwrprofpricersp(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Retrieve "Power Profile Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Currency" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_currency, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + + /* Retrieve "Price" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_price, tvb, *offset, 4, ENC_LITTLE_ENDIAN); + *offset += 4; + + /* Retrieve "Price Trailing Digit" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_price_trailing_digit, tvb, *offset, 1, ENC_NA); + *offset += 1; + +} /*dissect_zcl_pwr_prof_getpwrprofpricersp*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_getoverallschedpricersp + * DESCRIPTION + * this function is called in order to decode "GetOverallSchedulePriceResponse" + * payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_getoverallschedpricersp(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Retrieve "Currency" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_currency, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + + /* Retrieve "Price" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_price, tvb, *offset, 4, ENC_LITTLE_ENDIAN); + *offset += 4; + + /* Retrieve "Price Trailing Digit" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_price_trailing_digit, tvb, *offset, 1, ENC_NA); + *offset += 1; + +} /*dissect_zcl_pwr_prof_getoverallschedpricersp*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_sched_energy_phase + * DESCRIPTION + * this function is called in order to decode "ScheduledEnergyPhases" + * element. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_sched_energy_phase(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Energy Phase ID */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_energy_phase_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Scheduled Time */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_scheduled_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + +} /*dissect_zcl_sched_energy_phase*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_enphsschednotif + * DESCRIPTION + * this function is called in order to decode "EnergyPhasesScheduleNotification" + * and "EnergyPhasesScheduleResoponse" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_enphsschednotif(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + + guint i; + guint8 num_of_sched_phases; + + /* Retrieve "Power Profile Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Number of Scheduled Phases" field */ + num_of_sched_phases = tvb_get_guint8(tvb, *offset); + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_num_of_sched_phases, tvb, *offset, 1, ENC_NA); + *offset += 1; + + if (num_of_sched_phases != 0) + { + /* Scheduled Energy Phases decoding */ + for (i=0 ; i<num_of_sched_phases ; i++) { + /* Create subtree */ + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Energy Phase #%u", i); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_pwr_prof_enphases[i]); + + dissect_zcl_sched_energy_phase(tvb, sub_tree, offset); + } + } +} /*dissect_zcl_pwr_prof_enphsschednotif*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_energy_phase + * DESCRIPTION + * this function is called in order to decode "EnergyPhases" + * element. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_energy_phase(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_energy_phase_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_macro_phase_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_expect_duration, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_peak_power, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_energy, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_max_active_delay, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + +} /*dissect_zcl_energy_phase*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_pwrprofnotif + * DESCRIPTION + * this function is called in order to decode "PowerProfileNotification" + * and "PowerProfileResponse" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_pwrprofnotif(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + + guint i; + guint8 total_profile_number; + guint8 num_of_transferred_phases; + + /* Retrieve "Total Profile Number" field */ + total_profile_number = tvb_get_guint8(tvb, *offset); + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_tot_prof_num, tvb, *offset, 1, ENC_NA); + *offset += 1; + + if ( total_profile_number != 0 ) + { + /* Retrieve "Power Profile Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Number of Transferred Phases" field */ + num_of_transferred_phases = tvb_get_guint8(tvb, *offset); + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_num_of_trans_phases, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Energy Phases decoding */ + for ( i=0 ; i<num_of_transferred_phases ; i++) + { + /* Create subtree */ + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Energy Phase #%u", i); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_pwr_prof_enphases[i]); + + dissect_zcl_energy_phase(tvb, sub_tree, offset); + } + } +} + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_power_profile + * DESCRIPTION + * this function is called in order to decode "PowerProfile" + * element. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_power_profile(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Power Profile Id */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Energy Phase Id */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_energy_phase_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Power Profile Remote Control */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_rem_ctrl, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Power Profile State */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_state, tvb, *offset, 1, ENC_NA); + *offset += 1; + +} /*dissect_zcl_power_profile*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_pwrprofstatersp + * DESCRIPTION + * this function is called in order to decode "PowerProfileStateResponse" + * and "PowerProfileStateNotification" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_pwrprofstatersp(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + + guint i; + guint8 power_profile_count; + + /* Retrieve "Total Profile Number" field */ + power_profile_count = tvb_get_guint8(tvb, *offset); + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_count, tvb, *offset, 1, ENC_NA); + *offset += 1; + + if ( power_profile_count != 0 ) + { + /* Energy Phases decoding */ + for (i=0 ; i<power_profile_count ; i++) + { + /* Create subtree */ + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Power Profile #%u", i); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_pwr_prof_pwrprofiles[i]); + + dissect_zcl_power_profile(tvb, sub_tree, offset); + } + } +} /*dissect_zcl_pwr_prof_pwrprofstatersp*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_pwrprofschedcontrsnotif + * DESCRIPTION + * this function is called in order to decode "PowerProfileScheduleConstraintsNotification" + * and "PowerProfileScheduleConstraintsResponse" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_pwrprofschedcontrsnotif(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Retrieve "Power Profile Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Start After" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_start_after, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + + /* Retrieve "Stop Before" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_stop_before, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + +} /*dissect_zcl_pwr_prof_pwrprofschedcontrsnotif*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_pwrprofpriceext + * DESCRIPTION + * this function is called in order to decode "GetPowerProfilePriceExtended" + * and "PowerProfileScheduleConstraintsResponse" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_pwrprofpriceext(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_tree *sub_tree = NULL; + proto_item *ti; + guint8 options; + + /* Retrieve "Options" field */ + options = tvb_get_guint8(tvb, *offset); + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Options: 0x%02x", options); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_pwr_prof_options); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_options_01, tvb, *offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_options_res, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Power Profile Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Power Profile Start Time" field */ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_pwr_prof_stime, tvb, *offset, 2, ENC_LITTLE_ENDIAN); + *offset += 2; + +} /*dissect_zcl_pwr_prof_pwrprofpriceext*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_attr_id + * DESCRIPTION + * this function is called by ZCL foundation dissector in order to decode + * specific cluster attributes identifier. + * PARAMETERS + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * guint *offset - pointer to buffer offset + * guint16 attr_id - attribute identifier + * + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_attr_id(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id) +{ + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_attr_id, tvb, *offset, 2, attr_id); +} /*dissect_zcl_pwr_prof_attr_id*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_pwr_prof_attr_data + * DESCRIPTION + * this function is called by ZCL foundation dissector in order to decode + * specific cluster attributes data. + * PARAMETERS + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * guint *offset - pointer to buffer offset + * guint16 attr_id - attribute identifier + * guint data_type - attribute data type + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_pwr_prof_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + guint8 value8; + + /* Dissect attribute data type and data */ + switch ( attr_id ) + { + case ZBEE_ZCL_ATTR_ID_PWR_PROF_TOT_PROF_NUM: + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_tot_prof_num, tvb, *offset, 1, ENC_NA); + *offset += 1; + break; + + case ZBEE_ZCL_ATTR_ID_PWR_PROF_MULTIPLE_SCHED: + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_multiple_sched, tvb, *offset, 1, ENC_NA); + *offset += 1; + break; + + case ZBEE_ZCL_ATTR_ID_PWR_PROF_ENERGY_FORMAT: + value8 = tvb_get_guint8(tvb, *offset); + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Data: 0x%02x", value8); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_pwr_prof_en_format); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_energy_format_rdigit, tvb, *offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_energy_format_ldigit, tvb, *offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_energy_format_noleadingzero, tvb, *offset, 1, ENC_NA); + *offset += 1; + break; + + case ZBEE_ZCL_ATTR_ID_PWR_PROF_ENERGY_REMOTE: + proto_tree_add_item(tree, hf_zbee_zcl_pwr_prof_energy_remote, tvb, *offset, 1, ENC_NA); + *offset += 1; + break; + + case ZBEE_ZCL_ATTR_ID_PWR_PROF_SCHED_MODE: + value8 = tvb_get_guint8(tvb, *offset); + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Schedule Mode: 0x%02x", value8); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_pwr_prof_sched_mode); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_sched_mode_cheapest, tvb, *offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_sched_mode_greenest, tvb, *offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_pwr_prof_sched_mode_reserved, tvb, *offset, 1, ENC_NA); + *offset += 1; + break; + + default: + dissect_zcl_attr_data(tvb, tree, offset, data_type); + break; + } +} /*dissect_zcl_pwr_prof_attr_data*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * decode_power_profile_id + * DESCRIPTION + * this function decodes the power profile custom type + * PARAMETERS + * guint *s - string to display + * guint16 value - value to decode + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +decode_power_profile_id(gchar *s, guint8 id) +{ + if (id == 0) { + g_snprintf(s, ITEM_LABEL_LENGTH, "%d (All)", id); + } + else { + g_snprintf(s, ITEM_LABEL_LENGTH, "%d", id); + } +} /*decode_power_profile_id*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * decode_price_in_cents + * DESCRIPTION + * this function decodes price type variable + * PARAMETERS + * guint *s - string to display + * guint16 value - value to decode + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +decode_price_in_cents(gchar *s, guint32 value) +{ + g_snprintf(s, ITEM_LABEL_LENGTH, "%d cents", value); +} /* decode_price_in_cents */ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * decode_power_in_watt + * DESCRIPTION + * this function decodes watt power type variable + * PARAMETERS + * guint *s - string to display + * guint16 value - value to decode + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +decode_power_in_watt(gchar *s, guint16 value) +{ + g_snprintf(s, ITEM_LABEL_LENGTH, "%d Watt", value); +} /* decode_power_in_watt */ + +/*FUNCTION:------------------------------------------------------ + * NAME + * decode_energy + * DESCRIPTION + * this function decodes energy type variable + * PARAMETERS + * guint *s - string to display + * guint16 value - value to decode + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +decode_energy(gchar *s, guint16 value) +{ + g_snprintf(s, ITEM_LABEL_LENGTH, "%d Watt per hours", value); +} /* decode_energy */ + +/*FUNCTION:------------------------------------------------------ + * NAME + * func_decode_delayinminute + * DESCRIPTION + * this function decodes minute delay type variable + * PARAMETERS + * guint *s - string to display + * guint16 value - value to decode + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +func_decode_delayinminute(gchar *s, guint16 value) +{ + if (value == 0) { + g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes (Not permitted)", value); + } + else { + g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes", value); + } + +} /* func_decode_delayinminute*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * proto_register_zbee_zcl_pwr_prof + * DESCRIPTION + * ZigBee ZCL PowerProfile cluster protocol registration routine. + * PARAMETERS + * none + * RETURNS + * void + *--------------------------------------------------------------- + */ +void +proto_register_zbee_zcl_pwr_prof(void) +{ + guint i, j; + + static hf_register_info hf[] = { + + { &hf_zbee_zcl_pwr_prof_tot_prof_num, + { "Total Profile Number", "zbee_zcl_general.pwrprof.attr.totprofnum", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_multiple_sched, + { "Multiple Scheduling", "zbee_zcl_general.pwrprof.attr.multiplesched", FT_BOOLEAN, BASE_NONE, + TFS(&tfs_supported_not_supported), 0x0, NULL, HFILL } }, + +/* Begin EnergyFormatting fields */ + { &hf_zbee_zcl_pwr_prof_energy_format_rdigit, + { "Number of Digits to the right of the Decimal Point", "zbee_zcl_general.pwrprof.attr.energyformat.rdigit", + FT_UINT8, BASE_DEC, NULL, ZBEE_ZCL_OPT_PWRPROF_NUM_R_DIGIT, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_energy_format_ldigit, + { "Number of Digits to the left of the Decimal Point", "zbee_zcl_general.pwrprof.attr.energyformat.ldigit", + FT_UINT8, BASE_DEC, NULL, ZBEE_ZCL_OPT_PWRPROF_NUM_L_DIGIT, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_energy_format_noleadingzero, + { "Suppress leading zeros.", "zbee_zcl_general.pwrprof.attr.energyformat.noleadingzero", + FT_BOOLEAN, 8, TFS(&tfs_true_false), ZBEE_ZCL_OPT_PWRPROF_NO_LEADING_ZERO, NULL, HFILL } }, +/* End EnergyFormatting fields */ + + { &hf_zbee_zcl_pwr_prof_energy_remote, + { "Energy Remote", "zbee_zcl_general.pwrprof.attr.energyremote", FT_BOOLEAN, BASE_NONE, + TFS(&tfs_enabled_disabled), 0x0, NULL, HFILL } }, + +/* Begin ScheduleMode fields */ + { &hf_zbee_zcl_pwr_prof_sched_mode_cheapest, + { "Schedule Mode Cheapest", "zbee_zcl_general.pwrprof.attr.schedmode.cheapest", + FT_BOOLEAN, 8, TFS(&tfs_active_inactive), ZBEE_ZCL_OPT_PWRPROF_SCHED_CHEAPEST, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_sched_mode_greenest, + { "Schedule Mode Greenest", "zbee_zcl_general.pwrprof.attr.schedmode.greenest", + FT_BOOLEAN, 8, TFS(&tfs_active_inactive), ZBEE_ZCL_OPT_PWRPROF_SCHED_GREENEST, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_sched_mode_reserved, + { "Schedule Mode Reserved", "zbee_zcl_general.pwrprof.attr.schedmode.reserved", + FT_UINT8, BASE_HEX, NULL, ZBEE_ZCL_OPT_PWRPROF_SCHED_RESERVED, NULL, HFILL } }, +/* End ScheduleMode fields */ + + { &hf_zbee_zcl_pwr_prof_attr_id, + { "Attribute", "zbee_zcl_general.pwrprof.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_pwr_prof_attr_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_srv_tx_cmd_id, + { "Command", "zbee_zcl_general.pwrprof.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_pwr_prof_srv_tx_cmd_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_srv_rx_cmd_id, + { "Command", "zbee_zcl_general.pwrprof.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_pwr_prof_srv_rx_cmd_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_pwr_prof_id, + { "Power Profile ID", "zbee_zcl_general.pwrprof.pwrprofid", FT_UINT8, BASE_CUSTOM, decode_power_profile_id, 0x00, + "Identifier of the specific profile", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_currency, + { "Currency", "zbee_zcl_general.pwrprof.currency", FT_UINT16, BASE_HEX, VALS(zbee_zcl_currecy_names), 0x0, + "Local unit of currency (ISO 4217) used in the price field.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_price, + { "Price", "zbee_zcl_general.pwrprof.price", FT_UINT32, BASE_CUSTOM, decode_price_in_cents, 0x0, + "Price of the energy of a specific Power Profile.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_price_trailing_digit, + { "Price Trailing Digit", "zbee_zcl_general.pwrprof.pricetrailingdigit", FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of digits to the right of the decimal point.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_num_of_sched_phases, + { "Number of Scheduled Phases", "zbee_zcl_general.pwrprof.numofschedphases", FT_UINT8, BASE_DEC, NULL, 0x0, + "Total number of the energy phases of the Power Profile that need to be scheduled.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_energy_phase_id, + { "Energy Phase ID", "zbee_zcl_general.pwrprof.energyphaseid", FT_UINT8, BASE_DEC, NULL, 0x0, + "Identifier of the specific phase.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_scheduled_time, + { "Scheduled Time", "zbee_zcl_general.pwrprof.scheduledtime", FT_UINT16, BASE_CUSTOM, decode_zcl_time_in_minutes, 0x0, + NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_macro_phase_id, + { "Macro Phase ID", "zbee_zcl_general.pwrprof.macrophaseid", FT_UINT8, BASE_DEC, NULL, 0x0, + "Identifier of the specific energy phase.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_expect_duration, + { "Expected Duration", "zbee_zcl_general.pwrprof.expecduration", FT_UINT16, BASE_CUSTOM, decode_zcl_time_in_minutes, 0x0, + "The estimated duration of the specific phase.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_num_of_trans_phases, + { "Number of Transferred Phases", "zbee_zcl_general.pwrprof.numoftransphases", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_peak_power, + { "Peak Power", "zbee_zcl_general.pwrprof.peakpower", FT_UINT16, BASE_CUSTOM, decode_power_in_watt, 0x0, + "The estimated power for the specific phase.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_energy, + { "Energy", "zbee_zcl_general.pwrprof.energy", FT_UINT16, BASE_CUSTOM, decode_energy, 0x0, + "The estimated energy consumption for the accounted phase.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_max_active_delay, + { "Max Activation Delay", "zbee_zcl_general.pwrprof.maxactivdelay", FT_UINT16, BASE_CUSTOM, func_decode_delayinminute, 0x0, + "The maximum interruption time between the end of the previous phase and the beginning of the specific phase.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_pwr_prof_count, + { "Power Profile Count", "zbee_zcl_general.pwrprof.pwrprofcount", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_pwr_prof_rem_ctrl, + { "Power Profile Remote Control", "zbee_zcl_general.pwrprof.pwrprofremctrl", FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0x00, + "It indicates if the PowerProfile is currently remotely controllable or not.", HFILL } }, + + { &hf_zbee_zcl_pwr_prof_pwr_prof_state, + { "Power Profile State", "zbee_zcl_general.pwrprof.pwrprofstate", FT_UINT8, BASE_HEX, VALS(zbee_zcl_pwr_prof_state_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_start_after, + { "Start After", "zbee_zcl_general.pwrprof.startafter", FT_UINT16, BASE_CUSTOM, decode_zcl_time_in_minutes, 0x0, + NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_stop_before, + { "Stop Before", "zbee_zcl_general.pwrprof.stopbefore", FT_UINT16, BASE_CUSTOM, decode_zcl_time_in_minutes, 0x0, + NULL, HFILL } }, + +/* Begin Options fields */ + { &hf_zbee_zcl_pwr_prof_options_01, + { "PowerProfileStartTime Field Present", "zbee_zcl_general.pwrprof.options.01", FT_BOOLEAN, 8, TFS(&tfs_true_false), + ZBEE_ZCL_OPT_PWRPROF_STIME_PRESENT, NULL, HFILL } }, + + { &hf_zbee_zcl_pwr_prof_options_res, + { "Reserved", "zbee_zcl_general.pwrprof.options.reserved", FT_UINT8, BASE_HEX, NULL, + ZBEE_ZCL_OPT_PWRPROF_RESERVED, NULL, HFILL } }, +/* End Options fields */ + + { &hf_zbee_zcl_pwr_prof_pwr_prof_stime, + { "Power Profile Start Time", "zbee_zcl_general.pwrprof.pwrprofstime", FT_UINT16, BASE_CUSTOM, decode_zcl_time_in_minutes, 0x0, + NULL, HFILL } } + + }; + + /* ZCL PowerProfile subtrees */ + static gint *ett[ZBEE_ZCL_PWR_PROF_NUM_ETT]; + + ett[0] = &ett_zbee_zcl_pwr_prof; + ett[1] = &ett_zbee_zcl_pwr_prof_options; + ett[2] = &ett_zbee_zcl_pwr_prof_en_format; + ett[3] = &ett_zbee_zcl_pwr_prof_sched_mode; + + /* initialize attribute subtree types */ + for ( i = 0, j = ZBEE_ZCL_PWR_PROF_NUM_GENERIC_ETT; i < ZBEE_ZCL_PWR_PROF_NUM_PWR_PROF_ETT; i++, j++ ) { + ett_zbee_zcl_pwr_prof_pwrprofiles[i] = -1; + ett[j] = &ett_zbee_zcl_pwr_prof_pwrprofiles[i]; + } + + for ( i = 0; i < ZBEE_ZCL_PWR_PROF_NUM_EN_PHS_ETT; i++, j++ ) { + ett_zbee_zcl_pwr_prof_enphases[i] = -1; + ett[j] = &ett_zbee_zcl_pwr_prof_enphases[i]; + } + + /* Register the ZigBee ZCL PowerProfile cluster protocol name and description */ + proto_zbee_zcl_pwr_prof = proto_register_protocol("ZigBee ZCL Power Profile", "ZCL Power Profile", ZBEE_PROTOABBREV_ZCL_PWRPROF); + proto_register_field_array(proto_zbee_zcl_pwr_prof, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register the ZigBee ZCL Power Profile dissector. */ + register_dissector(ZBEE_PROTOABBREV_ZCL_PWRPROF, dissect_zbee_zcl_pwr_prof, proto_zbee_zcl_pwr_prof); + +} /* proto_register_zbee_zcl_pwr_prof */ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * proto_reg_handoff_zbee_zcl_pwr_prof + * DESCRIPTION + * Hands off the Zcl Power Profile cluster dissector. + * PARAMETERS + * none + * RETURNS + * void + *--------------------------------------------------------------- + */ +void +proto_reg_handoff_zbee_zcl_pwr_prof(void) +{ + dissector_handle_t pwr_prof_handle; + + /* Register our dissector with the ZigBee application dissectors. */ + pwr_prof_handle = find_dissector(ZBEE_PROTOABBREV_ZCL_PWRPROF); + dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_POWER_PROFILE, pwr_prof_handle); + + zbee_zcl_init_cluster( proto_zbee_zcl_pwr_prof, + ett_zbee_zcl_pwr_prof, + ZBEE_ZCL_CID_POWER_PROFILE, + (zbee_zcl_fn_attr_id)dissect_zcl_pwr_prof_attr_id, + (zbee_zcl_fn_attr_data)dissect_zcl_pwr_prof_attr_data + ); +} /*proto_reg_handoff_zbee_zcl_pwr_prof*/ + +/* ########################################################################## */ +/* #### (0x001B) APPLIANCE CONTROL CLUSTER ################################## */ +/* ########################################################################## */ + +/*************************/ +/* Defines */ +/*************************/ + +#define ZBEE_ZCL_APPL_CTRL_NUM_GENERIC_ETT 3 +#define ZBEE_ZCL_APPL_CTRL_NUM_FUNC_ETT 32 +#define ZBEE_ZCL_APPL_CTRL_NUM_ETT (ZBEE_ZCL_APPL_CTRL_NUM_GENERIC_ETT + \ + ZBEE_ZCL_APPL_CTRL_NUM_FUNC_ETT) + +/* Attributes */ +#define ZBEE_ZCL_ATTR_ID_APPL_CTRL_START_TIME 0x0000 /* Start Time */ +#define ZBEE_ZCL_ATTR_ID_APPL_CTRL_FINISH_TIME 0x0001 /* Finish Time */ +#define ZBEE_ZCL_ATTR_ID_APPL_CTRL_REMAINING_TIME 0x0002 /* Remaining Time */ + +/* Server Commands Received */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_EXECUTION_CMD 0x00 /* Execution of a Command */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE 0x01 /* Signal State */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_WRITE_FUNCS 0x02 /* Write Functions */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_PAUSE_RESUME 0x03 /* Overload Pause Resume */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_PAUSE 0x04 /* Overload Pause */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_WARNING 0x05 /* Overload Warning */ + +/* Server Commands Generated */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE_RSP 0x00 /* Signal State Response */ +#define ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE_NOTIF 0x01 /* Signal State Notification */ + +/* Execution Of a Command - Command Ids list */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_RESERVED 0x00 /* Reserved */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START 0x01 /* Start appliance cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_STOP 0x02 /* Stop appliance cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_PAUSE 0x03 /* Pause appliance cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START_SUPERFREEZING 0x04 /* Start superfreezing cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_STOP_SUPERFREEZING 0x05 /* Stop superfreezing cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START_SUPERCOOLING 0x06 /* Start supercooling cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_STOP_SUPERCOOLING 0x07 /* Stop supercooling cycle */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_DISABLE_GAS 0x08 /* Disable gas */ +#define ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_ENABLE_GAS 0x09 /* Enable gas */ + +/* CECED Time mask */ +#define ZBEE_ZCL_APPL_CTRL_TIME_MM 0x003f /* Minutes */ +#define ZBEE_ZCL_APPL_CTRL_TIME_ENCOD_TYPE 0x00c0 /* Encoding Type */ +#define ZBEE_ZCL_APPL_CTRL_TIME_HH 0xff00 /* Hours */ + +/* Time encoding values */ +#define ZBEE_ZCL_APPL_CTRL_TIME_ENCOD_REL 0x00 +#define ZBEE_ZCL_APPL_CTRL_TIME_ENCOD_ABS 0x01 + +/* Overload Warnings */ +#define ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_1 0x00 +#define ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_2 0x01 +#define ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_3 0x02 +#define ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_4 0x03 +#define ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_5 0x04 + +/* Appliance Status Ids list */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_RESERVED 0x00 /* Reserved */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_OFF 0x01 /* Appliance in off state */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_STANDBY 0x02 /* Appliance in stand-by */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_PRG 0x03 /* Appliance already programmed */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_PRG_WAITING_TO_START 0x04 /* Appliance already programmed and ready to start */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_RUNNING 0x05 /* Appliance is running */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_PAUSE 0x06 /* Appliance is in pause */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_END_PRG 0x07 /* Appliance end programmed tasks */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_FAILURE 0x08 /* Appliance is in a failure state */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_PRG_INTERRUPTED 0x09 /* The appliance programmed tasks have been interrupted */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_IDLE 0x1a /* Appliance in idle state */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_RINSE_HOLD 0x1b /* Appliance rinse hold */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_SERVICE 0x1c /* Appliance in service state */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_SUPERFREEZING 0x1d /* Appliance in superfreezing state */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_SUPERCOOLING 0x1e /* Appliance in supercooling state */ +#define ZBEE_ZCL_APPL_CTRL_ID_STATUS_SUPERHEATING 0x1f /* Appliance in superheating state */ + +/* Remote Enable Flags mask */ +#define ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_FLAGS 0x0f +#define ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_STATUS2 0xf0 + +/* Remote Enable Flags values */ +#define ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_DIS 0x00 /* Disabled */ +#define ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_EN_REM_EN_CTRL 0x01 /* Enable Remote and Energy Control */ +#define ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_TEMP_LOCK_DIS 0x07 /* Temporarily locked/disabled */ +#define ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_EN_REM_CTRL 0x0f /* Enable Remote Control */ + +/* Device Status 2 values */ +#define ZBEE_ZCL_APPL_CTRL_STATUS2_PROPRIETARY_0 0x00 /* Proprietary */ +#define ZBEE_ZCL_APPL_CTRL_STATUS2_PROPRIETARY_1 0x01 /* Proprietary */ +#define ZBEE_ZCL_APPL_CTRL_STATUS2_IRIS_SYMPTOM_CODE 0x02 /* Iris symptom code */ + +/*************************/ +/* Function Declarations */ +/*************************/ + +/* Command Dissector Helpers */ +static void dissect_zcl_appl_ctrl_exec_cmd (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_appl_ctrl_attr_func (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_appl_ctrl_wr_funcs (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_appl_ctrl_ovrl_warning (tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void dissect_zcl_appl_ctrl_signal_state_rsp (tvbuff_t *tvb, proto_tree *tree, guint *offset); + +/* Private functions prototype */ +static void dissect_zcl_appl_ctrl_attr_id (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id); +static void dissect_zcl_appl_ctrl_attr_data (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type); + + +/*************************/ +/* Global Variables */ +/*************************/ +/* Initialize the protocol and registered fields */ +static int proto_zbee_zcl_appl_ctrl = -1; + +static int hf_zbee_zcl_appl_ctrl_attr_id = -1; +static int hf_zbee_zcl_appl_ctrl_time_mm = -1; +static int hf_zbee_zcl_appl_ctrl_time_encoding_type = -1; +static int hf_zbee_zcl_appl_ctrl_time_hh = -1; +static int hf_zbee_zcl_appl_ctrl_srv_tx_cmd_id = -1; +static int hf_zbee_zcl_appl_ctrl_srv_rx_cmd_id = -1; +static int hf_zbee_zcl_appl_ctrl_exec_cmd_id = -1; +static int hf_zbee_zcl_appl_ctrl_attr_func_id = -1; +static int hf_zbee_zcl_appl_ctrl_attr_func_data_type = -1; +static int hf_zbee_zcl_appl_ctrl_warning_id = -1; +static int hf_zbee_zcl_appl_ctrl_appl_status = -1; +static int hf_zbee_zcl_appl_ctrl_rem_en_flags = -1; +static int hf_zbee_zcl_appl_ctrl_status2 = -1; +static int hf_zbee_zcl_appl_ctrl_status2_array = -1; + +/* Initialize the subtree pointers */ +static gint ett_zbee_zcl_appl_ctrl = -1; +static gint ett_zbee_zcl_appl_ctrl_flags = -1; +static gint ett_zbee_zcl_appl_ctrl_time = -1; +static gint ett_zbee_zcl_appl_ctrl_func[ZBEE_ZCL_APPL_CTRL_NUM_FUNC_ETT]; + +/* Attributes */ +static const value_string zbee_zcl_appl_ctrl_attr_names[] = { + { ZBEE_ZCL_ATTR_ID_APPL_CTRL_START_TIME, "Start Time" }, + { ZBEE_ZCL_ATTR_ID_APPL_CTRL_FINISH_TIME, "Finish Time" }, + { ZBEE_ZCL_ATTR_ID_APPL_CTRL_REMAINING_TIME, "Remaining Time" }, + { 0, NULL } +}; +static value_string_ext zbee_zcl_appl_ctrl_attr_names_ext = VALUE_STRING_EXT_INIT(zbee_zcl_appl_ctrl_attr_names); + +/* Server Commands Received */ +static const value_string zbee_zcl_appl_ctrl_srv_rx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_APPL_CTRL_EXECUTION_CMD, "Execution of a Command" }, + { ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE, "Signal State" }, + { ZBEE_ZCL_CMD_ID_APPL_CTRL_WRITE_FUNCS, "Write Functions" }, + { ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_PAUSE_RESUME, "Overload Pause Resume" }, + { ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_PAUSE, "Overload Pause" }, + { ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_WARNING, "Overload Warning" }, + { 0, NULL } +}; + +/* Server Commands Generated */ +static const value_string zbee_zcl_appl_ctrl_srv_tx_cmd_names[] = { + { ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE_RSP, "Signal State Response" }, + { ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE_NOTIF, "Signal State Notification" }, + { 0, NULL } +}; + +/* Execution Of a Command - Command Name */ +static const value_string zbee_zcl_appl_ctrl_exec_cmd_names[] = { + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_RESERVED, "Reserved" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START, "Start" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_STOP, "Stop" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_PAUSE, "Pause" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START_SUPERFREEZING, "Start Superfreezing" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START_SUPERFREEZING, "Stop Superfreezing" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_START_SUPERCOOLING, "Start Supercooling" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_STOP_SUPERCOOLING, "Stop Supercooling" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_DISABLE_GAS, "Disable Gas" }, + { ZBEE_ZCL_APPL_CTRL_EXEC_CMD_ID_ENABLE_GAS, "Enable Gas" }, + { 0, NULL } +}; + +/* Appliance Status Names list */ +static const value_string zbee_zcl_appl_ctrl_appl_status_names[] = { + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_RESERVED, "Reserved" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_OFF, "Off" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_STANDBY, "Stand-by" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_PRG, "Programmed" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_PRG_WAITING_TO_START, "Waiting to Start" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_RUNNING, "Running" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_PAUSE, "Pause" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_END_PRG, "End Programmed" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_FAILURE, "Failure" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_PRG_INTERRUPTED, "Programme Interrupted" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_IDLE, "Idle" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_RINSE_HOLD, "Raise Hold" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_SERVICE, "Service" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_SUPERFREEZING, "Superfreezing" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_SUPERCOOLING, "Supercooling" }, + { ZBEE_ZCL_APPL_CTRL_ID_STATUS_SUPERHEATING, "Superheating" }, + { 0, NULL } +}; + +/* Remote Enable Flags Names list */ +static const value_string zbee_zcl_appl_ctrl_rem_flags_names[] = { + { ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_DIS, "Disable" }, + { ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_EN_REM_EN_CTRL, "Enable Remote and Energy Control" }, + { ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_TEMP_LOCK_DIS, "Temporarily locked/disabled" }, + { ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_EN_REM_CTRL, "Enable Remote Control" }, + { 0, NULL } +}; + +/* Appliance Status 2 Names list */ +static const value_string zbee_zcl_appl_ctrl_status2_names[] = { + { ZBEE_ZCL_APPL_CTRL_STATUS2_PROPRIETARY_0, "Proprietary" }, + { ZBEE_ZCL_APPL_CTRL_STATUS2_PROPRIETARY_1, "Proprietary" }, + { ZBEE_ZCL_APPL_CTRL_STATUS2_IRIS_SYMPTOM_CODE, "Iris symptom code" }, + { 0, NULL } +}; + +/* Overload Warning Names list */ +static const value_string zbee_zcl_appl_ctrl_ovrl_warning_names[] = { + { ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_1, "Overall power above 'available power' level" }, + { ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_2, "Overall power above 'power threshold' level" }, + { ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_3, "Overall power back below the 'available power' level" }, + { ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_4, "Overall power back below the 'power threshold' level" }, + { ZBEE_ZCL_APPL_CTRL_ID_OVRL_WARN_5, "Overall power will be potentially above 'available power' level if the appliance starts" }, + { 0, NULL } +}; + +/* CEDEC Time Encoding Names list */ +static const value_string zbee_zcl_appl_ctrl_time_encoding_type_names[] = { + { ZBEE_ZCL_APPL_CTRL_TIME_ENCOD_REL, "Relative" }, + { ZBEE_ZCL_APPL_CTRL_TIME_ENCOD_ABS, "Absolute" }, + { 0, NULL } +}; + +/*************************/ +/* Function Bodies */ +/*************************/ + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zbee_zcl_appl_ctrl + * DESCRIPTION + * ZigBee ZCL Appliance Control cluster dissector for wireshark. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * packet_info *pinfo - pointer to packet information fields + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zbee_zcl_appl_ctrl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *payload_root = NULL; + proto_tree *payload_tree = NULL; + zbee_zcl_packet *zcl = (zbee_zcl_packet *)pinfo->private_data; + guint offset = 0; + guint8 cmd_id = zcl->cmd_id; + + /* Create a subtree for the ZCL Command frame, and add the command ID to it. */ + if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { + if (tree) { + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_srv_rx_cmd_id, tvb, offset, 1, cmd_id); + /* Check is this command has a payload, than add the payload tree */ + if (offset != (tvb_length(tvb) - 1)) { + payload_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Payload"); + payload_tree = proto_item_add_subtree(payload_root, ett_zbee_zcl_appl_ctrl); + } + } + offset += 1; + + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_appl_ctrl_srv_rx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Call the appropriate command dissector */ + switch (cmd_id) { + + case ZBEE_ZCL_CMD_ID_APPL_CTRL_EXECUTION_CMD: + dissect_zcl_appl_ctrl_exec_cmd(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE: + case ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_PAUSE_RESUME: + case ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_PAUSE: + /* No payload */ + break; + + case ZBEE_ZCL_CMD_ID_APPL_CTRL_WRITE_FUNCS: + dissect_zcl_appl_ctrl_wr_funcs(tvb, payload_tree, &offset); + break; + + case ZBEE_ZCL_CMD_ID_APPL_CTRL_OVERLOAD_WARNING: + dissect_zcl_appl_ctrl_ovrl_warning(tvb, payload_tree, &offset); + break; + + default: + break; + } + } + else { /* ZBEE_ZCL_FCF_TO_CLIENT */ + if (tree) { + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_srv_tx_cmd_id, tvb, offset, 1, cmd_id); + /* Check is this command has a payload, than add the payload tree */ + if (offset != (tvb_length(tvb) - 1)) { + payload_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Payload"); + payload_tree = proto_item_add_subtree(payload_root, ett_zbee_zcl_appl_ctrl); + } + } + offset += 1; + + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_appl_ctrl_srv_tx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + + /* Call the appropriate command dissector */ + switch (cmd_id) { + + case ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE_RSP: + case ZBEE_ZCL_CMD_ID_APPL_CTRL_SIGNAL_STATE_NOTIF: + dissect_zcl_appl_ctrl_signal_state_rsp(tvb, payload_tree, &offset); + break; + + default: + break; + } + } +} + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_exec_cmd + * DESCRIPTION + * this function is called in order to decode "ExecutionOfACommand" + * payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_exec_cmd(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Retrieve "Command Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_exec_cmd_id, tvb, *offset, 1, ENC_NA); + *offset += 1; +} /*dissect_zcl_appl_ctrl_exec_cmd*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_attr_func + * DESCRIPTION + * this function is called in order to decode "Function" element. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_attr_func(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + guint8 func_data_type; + guint16 func_id; + + /* ID */ + func_id = tvb_get_letohs(tvb, *offset); + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_attr_func_id, tvb, *offset, 2,ENC_LITTLE_ENDIAN); + *offset += 2; + + proto_item_append_text(tree, ", %s", + val_to_str_ext_const(func_id, &zbee_zcl_appl_ctrl_attr_names_ext, "Reserved")); + + /* Data Type */ + func_data_type = tvb_get_guint8(tvb, *offset); + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_attr_func_data_type, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Function Data Dissector */ + dissect_zcl_appl_ctrl_attr_data(tree, tvb, offset, func_id, func_data_type); + +} /*dissect_zcl_appl_ctrl_attr_func*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_wr_funcs + * DESCRIPTION + * this function is called in order to decode "WriteFunctions" + * payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_wr_funcs(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + guint tvb_len; + guint i = 0; + + tvb_len = tvb_length(tvb); + while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) { + /* Create subtree for attribute status field */ + ti = proto_tree_add_text(tree, tvb, *offset, 0, "Function #%d", i); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_appl_ctrl_func[i]); + i++; + + /* Dissect the attribute identifier */ + dissect_zcl_appl_ctrl_attr_func(tvb, sub_tree, offset); + } + +} /*dissect_zcl_appl_ctrl_wr_funcs*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_ovrl_warning + * DESCRIPTION + * this function is called in order to decode "OverloadWarning" + * payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_ovrl_warning(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + /* Retrieve "Warning Id" field */ + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_warning_id, tvb, *offset, 1, ENC_NA); + *offset += 1; + +} /*dissect_zcl_appl_ctrl_ovrl_warning*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_signal_state_rsp + * DESCRIPTION + * this function is called in order to decode "SignalStateResponse" + * "SignalStateNotification" payload. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * guint *offset - pointer to buffer offset + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_signal_state_rsp(tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + guint8 flags; + + /* Retrieve "Appliance Status" field */ + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_appl_status, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Remote Enable" field */ + flags = tvb_get_guint8(tvb, *offset); + ti = proto_tree_add_text(tree, tvb, *offset, 1, "Remote Enable Flags: 0x%02x", flags); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_appl_ctrl_flags); + proto_tree_add_item(sub_tree, hf_zbee_zcl_appl_ctrl_rem_en_flags, tvb, *offset, 1, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_appl_ctrl_status2, tvb, *offset, 1, ENC_NA); + *offset += 1; + + /* Retrieve "Appliance Status 2" field */ + proto_tree_add_item(tree, hf_zbee_zcl_appl_ctrl_status2_array, tvb, *offset, 3, ENC_BIG_ENDIAN); +} /*dissect_zcl_appl_ctrl_signal_state_rsp*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_attr_id + * DESCRIPTION + * this function is called by ZCL foundation dissector in order to decode + * specific cluster attributes identifier. + * PARAMETERS + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * guint *offset - pointer to buffer offset + * guint16 attr_id - attribute identifier + * + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_attr_id(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id) +{ + proto_tree_add_uint(tree, hf_zbee_zcl_appl_ctrl_attr_id, tvb, *offset, 2, attr_id); +} /*dissect_zcl_appl_ctrl_attr_id*/ + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_appl_ctrl_attr_data + * DESCRIPTION + * this function is called by ZCL foundation dissector in order to decode + * specific cluster attributes data. + * PARAMETERS + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * guint *offset - pointer to buffer offset + * guint16 attr_id - attribute identifier + * guint data_type - attribute data type + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zcl_appl_ctrl_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type) +{ + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + guint16 raw_time; + + /* Dissect attribute data type and data */ + switch (attr_id) { + + case ZBEE_ZCL_ATTR_ID_APPL_CTRL_START_TIME: + case ZBEE_ZCL_ATTR_ID_APPL_CTRL_FINISH_TIME: + case ZBEE_ZCL_ATTR_ID_APPL_CTRL_REMAINING_TIME: + raw_time = tvb_get_letohs(tvb, *offset); + raw_time = (raw_time << 8) | (raw_time >> 8); + ti = proto_tree_add_text(tree, tvb, *offset, 2, "Data: 0x%04x", raw_time); + sub_tree = proto_item_add_subtree(ti, ett_zbee_zcl_appl_ctrl_time); + + proto_tree_add_item(sub_tree, hf_zbee_zcl_appl_ctrl_time_mm, tvb, *offset, 2, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_appl_ctrl_time_encoding_type, tvb, *offset, 2, ENC_NA); + proto_tree_add_item(sub_tree, hf_zbee_zcl_appl_ctrl_time_hh, tvb, *offset, 2, ENC_NA); + *offset += 2; + break; + + default: + dissect_zcl_attr_data(tvb, tree, offset, data_type); + break; + } +} /*dissect_zcl_appl_ctrl_attr_data*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * proto_register_zbee_zcl_appl_ctrl + * DESCRIPTION + * this function registers the ZCL Appliance Control dissector + * and all its information. + * PARAMETERS + * none + * RETURNS + * none + *--------------------------------------------------------------- + */ +void proto_register_zbee_zcl_appl_ctrl + ( + void + ) +{ + guint i, j; + + static hf_register_info hf[] = { + + { &hf_zbee_zcl_appl_ctrl_attr_id, + { "Attribute", "zbee_zcl_general.applctrl.attr_id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_appl_ctrl_attr_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_time_mm, + { "Minutes", "zbee_zcl_general.applctrl.time.mm", FT_UINT16, BASE_DEC, NULL, ZBEE_ZCL_APPL_CTRL_TIME_MM, + NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_time_encoding_type, + { "Encoding Type", "zbee_zcl_general.applctrl.time.encoding_type", FT_UINT16, BASE_HEX, VALS(zbee_zcl_appl_ctrl_time_encoding_type_names), + ZBEE_ZCL_APPL_CTRL_TIME_ENCOD_TYPE, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_time_hh, + { "Hours", "zbee_zcl_general.applctrl.time.hh", FT_UINT16, BASE_DEC, NULL, ZBEE_ZCL_APPL_CTRL_TIME_HH, + NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_srv_tx_cmd_id, + { "Command", "zbee_zcl_general.applctrl.cmd.srv_tx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_srv_tx_cmd_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_srv_rx_cmd_id, + { "Command", "zbee_zcl_general.applctrl.cmd.srv_rx.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_srv_rx_cmd_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_appl_status, + { "Appliance Status", "zbee_zcl_general.applctrl.status", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_appl_status_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_rem_en_flags, + { "Remote Enable Flags", "zbee_zcl_general.applctrl.remenflags", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_rem_flags_names), + ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_FLAGS, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_status2, + { "Appliance Status 2", "zbee_zcl_general.applctrl.status2", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_status2_names), + ZBEE_ZCL_APPL_CTRL_REM_EN_FLAGS_STATUS2, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_status2_array, + { "Appliance Status 2", "zbee_zcl_general.applctrl.status2.array", FT_UINT24, BASE_HEX, NULL, + 0x00, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_exec_cmd_id, + { "Command", "zbee_zcl_general.applctrl.execcmd.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_exec_cmd_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_attr_func_id, + { "ID", "zbee_zcl_general.applctrl.attr_func.id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_appl_ctrl_attr_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_attr_func_data_type, + { "Data Type", "zbee_zcl_general.applctrl.attr_func.datatype", FT_UINT8, BASE_HEX, VALS(zbee_zcl_short_data_type_names), + 0x0, NULL, HFILL } }, + + { &hf_zbee_zcl_appl_ctrl_warning_id, + { "Warning", "zbee_zcl_general.applctrl.ovrlwarning.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_appl_ctrl_ovrl_warning_names), + 0x0, NULL, HFILL } } + + }; + + /* ZCL ApplianceControl subtrees */ + gint *ett[ZBEE_ZCL_APPL_CTRL_NUM_ETT]; + + ett[0] = &ett_zbee_zcl_appl_ctrl; + ett[1] = &ett_zbee_zcl_appl_ctrl_flags; + ett[2] = &ett_zbee_zcl_appl_ctrl_time; + + /* initialize attribute subtree types */ + for ( i = 0, j = ZBEE_ZCL_APPL_CTRL_NUM_GENERIC_ETT; i < ZBEE_ZCL_APPL_CTRL_NUM_FUNC_ETT; i++, j++) { + ett_zbee_zcl_appl_ctrl_func[i] = -1; + ett[j] = &ett_zbee_zcl_appl_ctrl_func[i]; + } + + /* Register the ZigBee ZCL ApplianceControl cluster protocol name and description */ + proto_zbee_zcl_appl_ctrl = proto_register_protocol("ZigBee ZCL Appliance Control", "ZCL Appliance Control", ZBEE_PROTOABBREV_ZCL_APPLCTRL); + proto_register_field_array(proto_zbee_zcl_appl_ctrl, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register the ZigBee ZCL Appliance Control dissector. */ + register_dissector(ZBEE_PROTOABBREV_ZCL_APPLCTRL, dissect_zbee_zcl_appl_ctrl, proto_zbee_zcl_appl_ctrl); + +} /*proto_register_zbee_zcl_appl_ctrl*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * proto_reg_handoff_zbee_zcl_appl_ctrl + * DESCRIPTION + * Hands off the Zcl Appliance Control dissector. + * PARAMETERS + * none + * RETURNS + * void + *--------------------------------------------------------------- + */ +void +proto_reg_handoff_zbee_zcl_appl_ctrl(void) +{ + dissector_handle_t appl_ctrl_handle; + + /* Register our dissector with the ZigBee application dissectors. */ + appl_ctrl_handle = find_dissector(ZBEE_PROTOABBREV_ZCL_APPLCTRL); + dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_APPLIANCE_CONTROL, appl_ctrl_handle); + + zbee_zcl_init_cluster( proto_zbee_zcl_appl_ctrl, + ett_zbee_zcl_appl_ctrl, + ZBEE_ZCL_CID_APPLIANCE_CONTROL, + (zbee_zcl_fn_attr_id)dissect_zcl_appl_ctrl_attr_id, + (zbee_zcl_fn_attr_data)dissect_zcl_appl_ctrl_attr_data + ); +} /*proto_reg_handoff_zbee_zcl_appl_ctrl*/ diff --git a/epan/dissectors/packet-zbee-zcl.c b/epan/dissectors/packet-zbee-zcl.c index 6bdc1f5610..3ec901626d 100644 --- a/epan/dissectors/packet-zbee-zcl.c +++ b/epan/dissectors/packet-zbee-zcl.c @@ -707,17 +707,17 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree zbee_zcl_packet packet; zbee_zcl_cluster_desc *desc; - + guint8 fcf; guint offset = 0; /* Init. */ memset(&packet, 0, sizeof(zbee_zcl_packet)); - + /* Fill the zcl cluster id */ zcl_cluster_id = pinfo->zbee_cluster_id; cluster_handle = dissector_get_uint_handle(zbee_zcl_dissector_table, zcl_cluster_id); - + /* Create the protocol tree */ if ( tree ) { proto_root = proto_tree_add_protocol_format(tree, proto_zbee_zcl, tvb, offset, @@ -788,10 +788,10 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree packet.cmd_id = tvb_get_guint8(tvb, offset); desc = zbee_zcl_get_cluster_desc(zcl_cluster_id); - if (desc != NULL) { + if (desc != NULL) { col_append_fstr(pinfo->cinfo, COL_INFO, "%s: ", desc->name); } - + /* Add command ID to the tree. */ if ( packet.frame_type == ZBEE_ZCL_FCF_PROFILE_WIDE ) { if ( tree ) { @@ -799,11 +799,11 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"), packet.tran_seqno); } - + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"), packet.tran_seqno); - + if ( zcl_tree ) { proto_tree_add_uint(zcl_tree, hf_zbee_zcl_cmd_id, tvb, offset, (int)1, packet.cmd_id); @@ -813,11 +813,11 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree else { /* Cluster Specific */ payload_tvb = tvb_new_subset_remaining(tvb, offset); - + if (cluster_handle != NULL) { /* Call the specific cluster dissector registered */ - pinfo->private_data = (void *)&packet; - call_dissector(cluster_handle, payload_tvb, pinfo, zcl_tree); + pinfo->private_data = (void *)&packet; + call_dissector(cluster_handle, payload_tvb, pinfo, zcl_tree); } else { proto_item_append_text(proto_root, ", Cluster-specific Command: 0x%02x, Seq: %u", @@ -2135,6 +2135,22 @@ void decode_zcl_time_in_seconds(gchar *s, guint16 value) /*FUNCTION:------------------------------------------------------ * NAME + * decode_zcl_time_in_minutes + * DESCRIPTION + * this function decodes minute time type variable + * PARAMETERS + * RETURNS + * none + *--------------------------------------------------------------- + */ +void decode_zcl_time_in_minutes(gchar *s, guint16 value) +{ + g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes", value); + return; +} /*decode_zcl_time_in_minutes*/ + +/*FUNCTION:------------------------------------------------------ + * NAME * proto_register_zbee_zcl * DESCRIPTION * ZigBee ZCL protocol registration routine. diff --git a/epan/dissectors/packet-zbee-zcl.h b/epan/dissectors/packet-zbee-zcl.h index 562ab8bb51..401b47bdb3 100644 --- a/epan/dissectors/packet-zbee-zcl.h +++ b/epan/dissectors/packet-zbee-zcl.h @@ -197,6 +197,7 @@ extern void dissect_zcl_read_attr_resp (tvbuff_t *tvb, packet_info *pinfo, proto /* Helper functions */ void decode_zcl_time_in_seconds (gchar *s, guint16 value); +void decode_zcl_time_in_minutes (gchar *s, guint16 value); void dissect_zcl_attr_data (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint data_type); void zbee_zcl_init_cluster(int proto, gint ett, guint16 cluster_id, zbee_zcl_fn_attr_id fn_attr_id, zbee_zcl_fn_attr_data fn_attr_data); zbee_zcl_cluster_desc *zbee_zcl_get_cluster_desc(guint16 cluster_id); diff --git a/epan/dissectors/packet-zbee.h b/epan/dissectors/packet-zbee.h index cb304cb59b..1f33ad24ba 100644 --- a/epan/dissectors/packet-zbee.h +++ b/epan/dissectors/packet-zbee.h @@ -787,6 +787,7 @@ #define ZBEE_PROTOABBREV_APS "zbee_aps" #define ZBEE_PROTOABBREV_APF "zbee_apf" #define ZBEE_PROTOABBREV_ZCL "zbee_zcl" +#define ZBEE_PROTOABBREV_ZCL_APPLCTRL "zbee_zcl_general.applctrl" #define ZBEE_PROTOABBREV_ZCL_BASIC "zbee_zcl_general.basic" #define ZBEE_PROTOABBREV_ZCL_IDENTIFY "zbee_zcl_general.identify" #define ZBEE_PROTOABBREV_ZCL_APPLEVTALT "zbee_zcl_ha.applevtalt" @@ -795,6 +796,7 @@ #define ZBEE_PROTOABBREV_ZCL_METIDT "zbee_zcl_ha.metidt" #define ZBEE_PROTOABBREV_ZCL_ONOFF "zbee_zcl_general.onoff" #define ZBEE_PROTOABBREV_ZCL_PART "zbee_zcl_general.part" +#define ZBEE_PROTOABBREV_ZCL_PWRPROF "zbee_zcl_general.pwrprof" #define ZBEE_PROTOABBREV_ZCL_ILLUMMEAS "zbee_zcl_meas_sensing.illummeas" #define ZBEE_PROTOABBREV_ZCL_PRESSMEAS "zbee_zcl_meas_sensing.pressmeas" #define ZBEE_PROTOABBREV_ZCL_RELHUMMEAS "zbee_zcl_meas_sensing.relhummeas" |