/** * Process and store all the panel settings from the raw buffers * * @param PowerlinkMode true if in Powerlink mode or false if in standard mode * @param defaultPanelType the default panel type to consider if not found in the raw buffers * @param timeSet the time in milliseconds used to set time and date; null if no sync time * requested */ public void process(boolean PowerlinkMode, PowerMaxPanelType defaultPanelType, Long timeSet) { // Identify panel type panelType = defaultPanelType; byte[] data = readSettings(PowerMaxSendType.DL_SERIAL, 7, 7); if (data != null) { try { panelType = PowerMaxPanelType.fromCode(data[0]); } catch (IllegalArgumentException e) { logger.warn("PowerMax alarm binding: unknwon panel type for code {}", data[0] & 0x000000FF); panelType = defaultPanelType; } } sensorTypes = new HashMap<Byte, String>(); if (panelType.isPowerMaster()) { sensorTypes.put((byte) 0x01, "Motion"); sensorTypes.put((byte) 0x04, "Camera"); sensorTypes.put((byte) 0x16, "Smoke"); sensorTypes.put((byte) 0x1A, "Temperature"); sensorTypes.put((byte) 0x2A, "Magnet"); sensorTypes.put((byte) 0xFE, "Wired"); } else { sensorTypes.put((byte) 0x03, "Motion"); sensorTypes.put((byte) 0x04, "Motion"); sensorTypes.put((byte) 0x05, "Magnet"); sensorTypes.put((byte) 0x06, "Magnet"); sensorTypes.put((byte) 0x07, "Magnet"); sensorTypes.put((byte) 0x0A, "Smoke"); sensorTypes.put((byte) 0x0B, "Gas"); sensorTypes.put((byte) 0x0C, "Motion"); sensorTypes.put((byte) 0x0F, "Wired"); } int zoneCnt = panelType.getWireless() + panelType.getWired(); int customCnt = panelType.getCustomZones(); int userCnt = panelType.getUserCodes(); int partitionCnt = panelType.getPartitions(); int sirenCnt = panelType.getSirens(); int keypad1wCnt = panelType.getKeypads1w(); int keypad2wCnt = panelType.getKeypads2w(); zoneNames = new String[] { "Attic", "Back door", "Basement", "Bathroom", "Bedroom", "Child room", "Closet", "Den", "Dining room", "Downstairs", "Emergency", "Fire", "Front door", "Garage", "Garage door", "Guest room", "Hall", "Kitchen", "Laundry room", "Living room", "Master bathroom", "Master bedroom", "Office", "Upstairs", "Utility room", "Yard", "Custom 1", "Custom 2", "Custom 3", "Custom 4", "Custom 5", "Not Installed" }; phoneNumbers = new String[] {null, null, null, null}; bellTime = 4; silentPanic = false; quickArm = false; bypassEnabled = false; partitionsEnabled = false; pinCodes = new String[userCnt]; for (int i = 0; i < userCnt; i++) { pinCodes[i] = null; } panelEprom = null; panelSoftware = null; panelSerial = null; zoneSettings = new PowerMaxZoneSettings[zoneCnt]; for (int i = 0; i < zoneCnt; i++) { zoneSettings[i] = null; } x10Settings = new PowerMaxX10Settings[NB_PGM_X10_DEVICES]; for (int i = 0; i < NB_PGM_X10_DEVICES; i++) { x10Settings[i] = null; } keypad1wEnrolled = new boolean[keypad1wCnt]; for (int i = 0; i < keypad1wCnt; i++) { keypad1wEnrolled[i] = false; } keypad2wEnrolled = new boolean[keypad2wCnt]; for (int i = 0; i < keypad2wCnt; i++) { keypad2wEnrolled[i] = false; } sirensEnrolled = new boolean[sirenCnt]; for (int i = 0; i < sirenCnt; i++) { sirensEnrolled[i] = false; } if (PowerlinkMode) { // Check time and date data = readSettings(PowerMaxSendType.DL_TIME, 0, 5); GregorianCalendar cal = new GregorianCalendar(); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.SECOND, data[0] & 0x000000FF); cal.set(Calendar.MINUTE, data[1] & 0x000000FF); cal.set(Calendar.HOUR_OF_DAY, data[2] & 0x000000FF); cal.set(Calendar.DAY_OF_MONTH, data[3] & 0x000000FF); cal.set(Calendar.MONTH, (data[4] & 0x000000FF) - 1); cal.set(Calendar.YEAR, (data[5] & 0x000000FF) + 2000); long timeRead = cal.getTimeInMillis(); logger.debug( String.format( "PowerMax alarm binding: date %02d/%02d/%04d time %02d:%02d:%02d", cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND))); // Check if time sync was OK if (timeSet != null) { cal.setTimeInMillis(timeSet); if ((timeRead - timeSet) <= 1000) { logger.info("PowerMax alarm binding: time sync OK"); } else { logger.warn("PowerMax alarm binding: time sync failed !"); } } // Process zone names for (int i = 0; i < (26 + customCnt); i++) { data = readSettings(PowerMaxSendType.DL_ZONESTR, i * 16, (i + 1) * 16 - 1); if ((data != null) && ((data[0] & 0x000000FF) != 0x000000FF)) { zoneNames[i] = new String(data, CHARSET).trim(); } } // Process communication settings for (int i = 0; i < phoneNumbers.length; i++) { data = readSettings(PowerMaxSendType.DL_PHONENRS, 8 * i, 8 * i + 7); if (data != null) { for (int j = 0; j < 8; j++) { if ((data[j] & 0x000000FF) != 0x000000FF) { if (j == 0) { phoneNumbers[i] = ""; } if (phoneNumbers[i] != null) { phoneNumbers[i] += String.format("%02X", data[j] & 0x000000FF); } } } } } // Process alarm settings data = readSettings(PowerMaxSendType.DL_COMMDEF, 0, 0x1B); if (data != null) { bellTime = data[3] & 0x000000FF; silentPanic = (data[0x19] & 0x00000010) == 0x00000010; quickArm = (data[0x1A] & 0x00000008) == 0x00000008; bypassEnabled = (data[0x1B] & 0x000000C0) != 0; } // Process user PIN codes data = readSettings( panelType.isPowerMaster() ? PowerMaxSendType.DL_MR_PINCODES : PowerMaxSendType.DL_PINCODES, 0, 2 * userCnt - 1); if (data != null) { for (int i = 0; i < userCnt; i++) { pinCodes[i] = String.format("%02X%02X", data[i * 2] & 0x000000FF, data[i * 2 + 1] & 0x000000FF); } } // Process EEPROM version data = readSettings(PowerMaxSendType.DL_PANELFW, 0, 15); if (data != null) { panelEprom = new String(data, CHARSET).trim(); } // Process software version data = readSettings(PowerMaxSendType.DL_PANELFW, 16, 31); if (data != null) { panelSoftware = new String(data, CHARSET).trim(); } // Process serial ID panelSerial = ""; data = readSettings(PowerMaxSendType.DL_SERIAL, 0, 5); if (data != null) { for (int i = 0; i <= 5; i++) { if ((data[i] & 0x000000FF) != 0x000000FF) { panelSerial += String.format("%02X", data[i] & 0x000000FF); } else { panelSerial += "."; } } } // Check if partitions are enabled byte[] partitions = readSettings(PowerMaxSendType.DL_PARTITIONS, 0, 0x10 + zoneCnt); if (partitions != null) { partitionsEnabled = (partitions[0] & 0x000000FF) == 1; } if (!partitionsEnabled) { partitionCnt = 1; } // Process zone settings data = readSettings(PowerMaxSendType.DL_ZONES, 0, zoneCnt * 4 - 1); byte[] zoneNr = null; byte[] dataMr = null; if (panelType.isPowerMaster()) { zoneNr = readSettings(PowerMaxSendType.DL_MR_ZONENAMES, 0, zoneCnt - 1); dataMr = readSettings(PowerMaxSendType.DL_MR_ZONES, 0, zoneCnt * 10 - 2); } else { zoneNr = readSettings(PowerMaxSendType.DL_ZONENAMES, 0, zoneCnt - 1); } if ((data != null) && (zoneNr != null)) { byte[] zero3 = new byte[] {0, 0, 0}; byte[] zero5 = new byte[] {0, 0, 0, 0, 0}; for (int i = 0; i < zoneCnt; i++) { String zoneName = zoneNames[zoneNr[i] & 0x0000001F]; boolean zoneEnrolled; byte zoneInfo; byte sensorId; String sensorType; if (panelType.isPowerMaster()) { zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(dataMr, i * 10 + 4, i * 10 + 9), zero5); zoneInfo = data[i]; sensorId = dataMr[i * 10 + 5]; sensorType = sensorTypes.get(sensorId); } else { zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); zoneInfo = data[i * 4 + 3]; sensorId = data[i * 4 + 2]; sensorType = sensorTypes.get((byte) (sensorId & 0x0000000F)); } if (zoneEnrolled) { byte zoneType = (byte) (zoneInfo & 0x0000000F); byte zoneChime = (byte) ((zoneInfo >> 4) & 0x00000003); boolean[] part = new boolean[partitionCnt]; if (partitionCnt > 1) { for (int j = 0; j < partitionCnt; j++) { part[j] = (partitions != null) ? ((partitions[0x11 + i] & (1 << j)) != 0) : true; } } else { part[0] = true; } zoneSettings[i] = new PowerMaxZoneSettings(zoneName, zoneType, zoneChime, sensorType, part); } } } data = readSettings(PowerMaxSendType.DL_PGMX10, 0, 148); zoneNr = readSettings(PowerMaxSendType.DL_X10NAMES, 0, NB_PGM_X10_DEVICES - 2); if ((data != null) && (zoneNr != null)) { for (int i = 0; i < NB_PGM_X10_DEVICES; i++) { boolean enabled = false; String zoneName = null; for (int j = 0; j <= 8; j++) { if (data[5 + i + j * 0x10] != 0) { enabled = true; break; } } if (i > 0) { zoneName = zoneNames[zoneNr[i - 1] & 0x0000001F]; } x10Settings[i] = new PowerMaxX10Settings(zoneName, enabled); } } if (panelType.isPowerMaster()) { // Process 2 way keypad settings data = readSettings(PowerMaxSendType.DL_MR_KEYPADS, 0, keypad2wCnt * 10 - 1); if (data != null) { byte[] zero5 = new byte[] {0, 0, 0, 0, 0}; for (int i = 0; i < keypad2wCnt; i++) { keypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), zero5); } } // Process siren settings data = readSettings(PowerMaxSendType.DL_MR_SIRENS, 0, sirenCnt * 10 - 1); if (data != null) { byte[] zero5 = new byte[] {0, 0, 0, 0, 0}; for (int i = 0; i < sirenCnt; i++) { sirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), zero5); } } } else { // Process 1 way keypad settings data = readSettings(PowerMaxSendType.DL_1WKEYPAD, 0, keypad1wCnt * 4 - 1); if (data != null) { byte[] zero2 = new byte[] {0, 0}; for (int i = 0; i < keypad1wCnt; i++) { keypad1wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 2), zero2); } } // Process 2 way keypad settings data = readSettings(PowerMaxSendType.DL_2WKEYPAD, 0, keypad2wCnt * 4 - 1); if (data != null) { byte[] zero3 = new byte[] {0, 0, 0}; for (int i = 0; i < keypad2wCnt; i++) { keypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); } } // Process siren settings data = readSettings(PowerMaxSendType.DL_SIRENS, 0, sirenCnt * 4 - 1); if (data != null) { byte[] zero3 = new byte[] {0, 0, 0}; for (int i = 0; i < sirenCnt; i++) { sirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); } } } } else { if (!partitionsEnabled) { partitionCnt = 1; } boolean[] part = new boolean[partitionCnt]; for (int j = 0; j < partitionCnt; j++) { part[j] = true; } for (int i = 0; i < zoneCnt; i++) { zoneSettings[i] = new PowerMaxZoneSettings(null, (byte) 0xFF, (byte) 0xFF, null, part); } } }