org.energy_home.jemma.osgi.ah.zigbee.appliances.generic.ZclGenericAppliance.java Source code

Java tutorial

Introduction

Here is the source code for org.energy_home.jemma.osgi.ah.zigbee.appliances.generic.ZclGenericAppliance.java

Source

/**
 * This file is part of JEMMA - http://jemma.energy-home.org
 * (C) Copyright 2013 Telecom Italia (http://www.telecomitalia.it)
 *
 * JEMMA is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (LGPL) version 3
 * or later as published by the Free Software Foundation, which accompanies
 * this distribution and is available at http://www.gnu.org/licenses/lgpl.html
 *
 * JEMMA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License (LGPL) for more details.
 *
 */
package org.energy_home.jemma.osgi.ah.zigbee.appliances.generic;

import org.energy_home.jemma.ah.hac.ApplianceException;
import org.energy_home.jemma.ah.hac.IAppliance;
import org.energy_home.jemma.ah.hac.IEndPoint;
import org.energy_home.jemma.ah.zigbee.zcl.lib.ZclAppliance;
import org.energy_home.jemma.ah.zigbee.zcl.lib.ZclEndPoint;
import org.energy_home.jemma.ah.zigbee.zcl.lib.ZclEndPointFactory;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ZclGenericAppliance extends ZclAppliance {
    private static final Log log = LogFactory.getLog(ZclGenericAppliance.class);

    private static final String ZIGBEE_CONFIG_PROPERTY_NAME = IAppliance.APPLIANCE_CUSTOM_PROPERTIES_PREXIF
            + "config";

    private static final String SEPARATOR = "|";
    private static final String EMPTY_VALUE = "/";
    private static final String ARRAY_SEPARATOR = ",";

    static class ZclEndPointDescriptor {
        int appEndPointId;
        int endPointId;
        int profileId;
        int deviceId;
        int[] clientClusterIds;
        int[] serverClusterIds;

        static private int[] parseIntArray(String strArray) {
            if (strArray.equals(EMPTY_VALUE))
                return new int[0];
            StringTokenizer st = new StringTokenizer(strArray, ARRAY_SEPARATOR);
            int[] result = new int[st.countTokens()];
            int i = 0;
            while (st.hasMoreTokens()) {
                result[i] = Integer.parseInt(st.nextToken());
                i++;
            }
            return result;
        }

        static private void appendIntArray(int[] value, StringBuilder sb) {
            if (value == null || value.length == 0) {
                sb.append(EMPTY_VALUE);
            } else {
                for (int i = 0; i < value.length; i++) {
                    sb.append(value[i]);
                    if (i < value.length - 1)
                        sb.append(ARRAY_SEPARATOR);
                }
            }
        }

        public ZclEndPointDescriptor(int appEndPointId, int profileId, int deviceId, int endPointId,
                int[] clientClusterIds, int[] serverClusterIds) {
            this.appEndPointId = appEndPointId;
            this.endPointId = endPointId;
            this.profileId = profileId;
            this.deviceId = deviceId;
            this.clientClusterIds = clientClusterIds;
            this.serverClusterIds = serverClusterIds;
        }

        public ZclEndPointDescriptor(String value) throws ApplianceException {
            StringTokenizer st = new StringTokenizer(value, SEPARATOR);
            try {
                this.appEndPointId = Integer.parseInt(st.nextToken());
                this.profileId = Integer.parseInt(st.nextToken());
                this.deviceId = Integer.parseInt(st.nextToken());
                this.endPointId = Integer.parseInt(st.nextToken());
                clientClusterIds = parseIntArray(st.nextToken());
                serverClusterIds = parseIntArray(st.nextToken());
            } catch (Exception e) {
                throw new ApplianceException("Invalid end point configuration");
            }
        }

        public String toString() {
            StringBuilder sb = new StringBuilder(String.valueOf(SEPARATOR));
            sb.append(appEndPointId);
            sb.append(SEPARATOR);
            sb.append(profileId);
            sb.append(SEPARATOR);
            sb.append(deviceId);
            sb.append(SEPARATOR);
            sb.append(endPointId);
            sb.append(SEPARATOR);
            appendIntArray(clientClusterIds, sb);
            sb.append(SEPARATOR);
            appendIntArray(serverClusterIds, sb);
            sb.append(SEPARATOR);
            return sb.toString();
        }
    }

    private static int[] toIntArray(List list) {
        if (list == null)
            return new int[0];
        int size = list.size();
        int[] result = new int[size];
        int i = 0;
        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
            Integer value = (Integer) iterator.next();
            if (value == null)
                throw new IllegalStateException();
            result[i] = value.intValue();
            i++;
        }
        return result;
    }

    private List customConfiguration = null;

    private ZclEndPoint zclAllocateEndPoint(int app_end_point_id, int profile_id, int device_id, int end_point_id,
            int manufacturer_code, int[] clientClusterIds, int[] serverClusterIds) throws ApplianceException {
        ZclEndPoint endPoint = ZclEndPointFactory.getEndPoint(profile_id, device_id);
        this.addEndPoint(endPoint, app_end_point_id);
        ZclEndPointFactory.addServiceClusters(endPoint, profile_id, device_id, clientClusterIds, serverClusterIds);
        return endPoint;
    }

    protected boolean isGenericAppliance() {
        return true;
    }

    public Dictionary getCustomConfiguration() {
        Hashtable result = new Hashtable(1);
        String[] zigbeeConfigParameters = null;
        if (customConfiguration != null && customConfiguration.size() > 0) {
            zigbeeConfigParameters = new String[customConfiguration.size()];
            int i = 0;
            for (Iterator iterator = customConfiguration.iterator(); iterator.hasNext();) {
                ZclEndPointDescriptor epd = (ZclEndPointDescriptor) iterator.next();
                zigbeeConfigParameters[i] = epd.toString();
                i++;
            }
        }
        result.put(ZIGBEE_CONFIG_PROPERTY_NAME, zigbeeConfigParameters);
        return result;
    }

    public ZclGenericAppliance(String pid, Dictionary config) throws ApplianceException {
        super(pid, config);
        //      Integer[] endPointIds = null;
        //      try {
        //         int[] endPointIdsPrimitive = (int[]) config.get(IAppliance.APPLIANCE_EPS_IDS_PROPERTY);
        //         if (endPointIdsPrimitive != null) {
        //            endPointIds = new Integer[endPointIdsPrimitive.length];
        //            for (int i = 0; i < endPointIdsPrimitive.length; i++) {
        //               endPointIds[i] = new Integer(endPointIdsPrimitive[i]);
        //            }            
        //         }
        //      } catch (Exception e) {
        //         // FIXME: Sometimes an array of Integer object is stored in configuration admin
        //         endPointIds = (Integer[]) config.get(IAppliance.APPLIANCE_EPS_IDS_PROPERTY);
        //      }
        //      String[] endPointTypes = (String[]) config.get(IAppliance.APPLIANCE_EPS_TYPES_PROPERTY);
        String[] customConfigurationObject = (String[]) config.get(ZIGBEE_CONFIG_PROPERTY_NAME);
        customConfiguration = new ArrayList();
        ZclEndPointDescriptor epd = null;
        if (customConfigurationObject != null) {
            for (int i = 0; i < customConfigurationObject.length; i++) {
                epd = new ZclEndPointDescriptor(customConfigurationObject[i]);
                customConfiguration.add(epd);
            }
        }
        // Automatic allocation of ep 0
        for (Iterator iterator = customConfiguration.iterator(); iterator.hasNext();) {
            epd = (ZclEndPointDescriptor) iterator.next();
            zclAllocateEndPoint(epd.appEndPointId, epd.profileId, epd.deviceId, epd.endPointId, 0,
                    epd.clientClusterIds, epd.serverClusterIds);
        }
        return;
    }

    protected void attached() {
        log.debug("attached");
        // Here can be added with a timer critical initialization code (e.g. sleeping end device reporting configuration, reading zone status type,...)
        // Also additional custom appliance configuration can be updated (e.g. device subtype like ias contact, ias leak, ...)  
    }

    protected void detached() {
        log.debug("detached");
    }

    protected synchronized ZclEndPoint zclGetEndPoint(int epsNumber, int profile_id, int device_id,
            int end_point_id, int manufacturer_code, List clientClusterIds, List serverClusterIds)
            throws ApplianceException {
        ZclEndPoint endPoint = null;
        int applEndPointId = end_point_id;
        if (epsNumber == 1)
            // Used for compatibility: device with only one end point always use end point id 1
            applEndPointId = IEndPoint.DEFAULT_END_POINT_ID;
        endPoint = (ZclEndPoint) this.getEndPoint(applEndPointId);

        if (endPoint == null) {
            int[] clientIntClusterIds = toIntArray(clientClusterIds);
            int[] serverIntClusterIds = toIntArray(serverClusterIds);
            endPoint = zclAllocateEndPoint(applEndPointId, profile_id, device_id, end_point_id, manufacturer_code,
                    clientIntClusterIds, serverIntClusterIds);
            ZclEndPointDescriptor epd = new ZclEndPointDescriptor(applEndPointId, profile_id, device_id,
                    end_point_id, clientIntClusterIds, serverIntClusterIds);
            customConfiguration.add(epd);
        }
        return endPoint;
    }

}