/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.primare.internal.protocol.spa20; import org.openhab.binding.primare.internal.protocol.PrimareMessage; import org.openhab.binding.primare.internal.protocol.PrimareUtils; import org.openhab.core.library.types.DecimalType; import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class for Primare SP31.7/SP31/SPA20/SPA21 messages * * @author Veli-Pekka Juslin * @since 1.7.0 */ public class PrimareSPA20Message extends PrimareMessage { private static final Logger logger = LoggerFactory.getLogger(PrimareSPA20Message.class); /** * Constructor, use device command (String) and OpenHAB command * (org.openhab.core.types.Command) instances to build a PrimareSPA20Message * * @throws Exception */ public PrimareSPA20Message(Command command, String deviceCmdString) { this(command, PrimareSPA20Command.valueOf(deviceCmdString)); } /** * Constructor, use device command (PrimareSPA20Command) and OpenHAB command * (org.openhab.core.types.Command) instances to build a PrimareSPA20Message * * @throws Exception */ public PrimareSPA20Message(Command command, PrimareSPA20Command deviceCmd) { byte[] message = null; switch (deviceCmd) { // Variable 1 = Power/Standby 0..1, 0=Standby (default), 1=Operate case POWER_QUERY: message = PrimareSPA20Message.queryDeviceVariable(1); break; case POWER_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(1); break; case POWER_OFF: message = PrimareSPA20Message.setDeviceVariable(1, 0); break; case POWER_ON: message = PrimareSPA20Message.setDeviceVariable(1, 1); break; // Variable 2 = Main Input number 1..15 case MAIN_INPUT_QUERY: message = PrimareSPA20Message.queryDeviceVariable(2); break; case MAIN_INPUT_UP: message = PrimareSPA20Message.incDeviceVariable(2); break; case MAIN_INPUT_DOWN: message = PrimareSPA20Message.decDeviceVariable(2); break; case MAIN_INPUT_SET: message = PrimareSPA20Message.setDeviceVariable(2, ((DecimalType) command).intValue()); break; // Variable 3 = Volume level 0..99, default:0 case VOLUME_QUERY: message = PrimareSPA20Message.queryDeviceVariable(3); break; case VOLUME_UP: message = PrimareSPA20Message.incDeviceVariable(3); break; case VOLUME_DOWN: message = PrimareSPA20Message.decDeviceVariable(3); break; case VOLUME_SET: message = PrimareSPA20Message.setDeviceVariable(3, ((DecimalType) command).intValue()); break; // Variable 4 = Balance -20..+20, default:0 case BALANCE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(4); break; case BALANCE_UP: message = PrimareSPA20Message.stepDeviceVariable(4, 1); break; case BALANCE_DOWN: message = PrimareSPA20Message.stepDeviceVariable(4, -1); break; case BALANCE_SET: message = PrimareSPA20Message.setDeviceVariable(4, ((DecimalType) command).intValue()); break; // Variable 5 = Center -20..+20, default:0 case CENTER_QUERY: message = PrimareSPA20Message.queryDeviceVariable(5); break; case CENTER_UP: message = PrimareSPA20Message.stepDeviceVariable(5, 1); break; case CENTER_DOWN: message = PrimareSPA20Message.stepDeviceVariable(5, -1); break; case CENTER_SET: message = PrimareSPA20Message.setDeviceVariable(5, ((DecimalType) command).intValue()); break; // Variable 6 = Surround -20..+20, default:0 case SURROUND_QUERY: message = PrimareSPA20Message.queryDeviceVariable(6); break; case SURROUND_UP: message = PrimareSPA20Message.stepDeviceVariable(6, 1); break; case SURROUND_DOWN: message = PrimareSPA20Message.stepDeviceVariable(6, -1); break; case SURROUND_SET: message = PrimareSPA20Message.setDeviceVariable(6, ((DecimalType) command).intValue()); break; // Variable 7 = Back -20..+20, default:0 case BACK_QUERY: message = PrimareSPA20Message.queryDeviceVariable(7); break; case BACK_UP: message = PrimareSPA20Message.stepDeviceVariable(7, 1); break; case BACK_DOWN: message = PrimareSPA20Message.stepDeviceVariable(7, -1); break; case BACK_SET: message = PrimareSPA20Message.setDeviceVariable(7, ((DecimalType) command).intValue()); break; // Variable 8 = SUB -20..+20, default:0 case SUB_QUERY: message = PrimareSPA20Message.queryDeviceVariable(8); break; case SUB_UP: message = PrimareSPA20Message.stepDeviceVariable(8, 1); break; case SUB_DOWN: message = PrimareSPA20Message.stepDeviceVariable(8, -1); break; case SUB_SET: message = PrimareSPA20Message.setDeviceVariable(8, ((DecimalType) command).intValue()); break; // Variable 9 = Mute 0..1, 0=inactive (default), 1=active case MUTE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(9); break; case MUTE_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(9); break; case MUTE_OFF: message = PrimareSPA20Message.setDeviceVariable(9, 0); break; case MUTE_ON: message = PrimareSPA20Message.setDeviceVariable(9, 1); break; // Variable 10 = Dim 0..1, 0=display on, 1=display off (default) case DIM_QUERY: message = PrimareSPA20Message.queryDeviceVariable(10); break; case DIM_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(10); break; case DIM_OFF: // 1 = Display on (Dim off) message = PrimareSPA20Message.setDeviceVariable(10, 1); break; case DIM_ON: // 0 = Display off (Dim on) message = PrimareSPA20Message.setDeviceVariable(10, 0); break; // Variable 11 = Record Input number 1..15 case RECORD_INPUT_QUERY: message = PrimareSPA20Message.queryDeviceVariable(11); break; case RECORD_INPUT_UP: message = PrimareSPA20Message.incDeviceVariable(11); break; case RECORD_INPUT_DOWN: message = PrimareSPA20Message.decDeviceVariable(11); break; case RECORD_INPUT_SET: message = PrimareSPA20Message.setDeviceVariable(11, ((DecimalType) command).intValue()); break; // Variable 12 = Surround mode 0..6 case SURROUND_MODE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(12); break; case SURROUND_MODE_UP: message = PrimareSPA20Message.incDeviceVariable(12); break; case SURROUND_MODE_SET: message = PrimareSPA20Message.setDeviceVariable(12, ((DecimalType) command).intValue()); break; // Variable 13 = Verbose 0..1, 1=verbose on, 2=verbose off (default) case VERBOSE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(13); break; case VERBOSE_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(13); break; case VERBOSE_OFF: message = PrimareSPA20Message.setDeviceVariable(13, 0); break; case VERBOSE_ON: message = PrimareSPA20Message.setDeviceVariable(13, 1); break; // Variable 14 = Menu 0..2, 0 = Exit menu (default), 1=Menu back, 2=Enter menu case MENU_QUERY: message = PrimareSPA20Message.queryDeviceVariable(14); break; case MENU_TOGGLE: // Menu enter / menu back message = PrimareSPA20Message.toggleDeviceVariable(14); break; case MENU_SET: message = PrimareSPA20Message.setDeviceVariable(14, ((DecimalType) command).intValue()); break; // Variable 16 = Extra surround mode 0..1 case EXTRA_SURROUND_MODE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(16); break; case EXTRA_SURROUND_MODE_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(16); break; case EXTRA_SURROUND_MODE_ON: message = PrimareSPA20Message.setDeviceVariable(16, 1); break; case EXTRA_SURROUND_MODE_OFF: message = PrimareSPA20Message.setDeviceVariable(16, 0); break; // Variable 17 = Front panel lock 0..1, 0 = lock off (default), 1 = lock on case FRONT_PANEL_LOCK_QUERY: message = PrimareSPA20Message.queryDeviceVariable(17); break; case FRONT_PANEL_LOCK_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(17); break; case FRONT_PANEL_LOCK_OFF: message = PrimareSPA20Message.setDeviceVariable(17, 0); break; case FRONT_PANEL_LOCK_ON: message = PrimareSPA20Message.setDeviceVariable(17, 1); break; // Variable 18 = IR Input select 0..1, 0 = front ir input (default), other = back ir input case IR_INPUT_QUERY: message = PrimareSPA20Message.queryDeviceVariable(18); break; case IR_INPUT_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(18); break; case IR_INPUT_FRONT: message = PrimareSPA20Message.setDeviceVariable(18, 0); break; case IR_INPUT_BACK: message = PrimareSPA20Message.setDeviceVariable(18, 1); break; // Variable 19 = Recall settings 0..2, 0=factory settings, 1=memory factory settings 2=memory installer // settings case RECALL_MEMORY: message = PrimareSPA20Message.toggleDeviceVariable(19); break; case RECALL_MEMORY_DIRECT_USER_SETTINGS: message = PrimareSPA20Message.setDeviceVariable(19, 0); break; case RECALL_MEMORY_DIRECT_FACTORY_SETTINGS: message = PrimareSPA20Message.setDeviceVariable(19, 1); break; case RECALL_MEMORY_DIRECT_INSTALLER_SETTINGS: message = PrimareSPA20Message.setDeviceVariable(19, 2); break; // Variable 20 = Current input 1..15 case CURRENT_INPUT_NAME_QUERY: message = PrimareSPA20Message.queryDeviceVariable(20); break; // Variable 21 = name of productline case PRODUCTLINE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(21); break; // Variable 22 = name of model case MODEL_QUERY: message = PrimareSPA20Message.queryDeviceVariable(22); break; // Variable 23 = software version case SW_VERSION_QUERY: message = PrimareSPA20Message.queryDeviceVariable(23); break; // Variable 25 = Late night mode 0..1, 0=off (default), 1=on case LATE_NIGHT_MODE_QUERY: message = PrimareSPA20Message.queryDeviceVariable(25); break; case LATE_NIGHT_MODE_TOGGLE: message = PrimareSPA20Message.toggleDeviceVariable(25); break; case LATE_NIGHT_MODE_OFF: message = PrimareSPA20Message.setDeviceVariable(25, 0); break; case LATE_NIGHT_MODE_ON: message = PrimareSPA20Message.setDeviceVariable(25, 1); break; // Composite message: full status query case ALL_QUERY: messageParts = new byte[][] { PrimareSPA20Message.queryDeviceVariable(1), PrimareSPA20Message.queryDeviceVariable(2), PrimareSPA20Message.queryDeviceVariable(3), PrimareSPA20Message.queryDeviceVariable(4), PrimareSPA20Message.queryDeviceVariable(5), PrimareSPA20Message.queryDeviceVariable(6), PrimareSPA20Message.queryDeviceVariable(7), PrimareSPA20Message.queryDeviceVariable(8), PrimareSPA20Message.queryDeviceVariable(9), PrimareSPA20Message.queryDeviceVariable(10), PrimareSPA20Message.queryDeviceVariable(11), PrimareSPA20Message.queryDeviceVariable(12), PrimareSPA20Message.queryDeviceVariable(13), PrimareSPA20Message.queryDeviceVariable(14), PrimareSPA20Message.queryDeviceVariable(16), PrimareSPA20Message.queryDeviceVariable(17), PrimareSPA20Message.queryDeviceVariable(18), PrimareSPA20Message.queryDeviceVariable(20), PrimareSPA20Message.queryDeviceVariable(21), PrimareSPA20Message.queryDeviceVariable(22), PrimareSPA20Message.queryDeviceVariable(23), PrimareSPA20Message.queryDeviceVariable(25) }; break; } if (message != null) { messageParts = new byte[][] { message }; } logger.trace("New PrimareSPA20Message is (hex) [{}]", PrimareUtils.byteArraysToHex(messageParts)); } /* * Utility functions */ public static byte[] setDeviceVariable(int var_number, String paramValue) { return setDeviceVariable(var_number, (byte) Integer.parseInt(paramValue)); } public static byte[] setDeviceVariable(int var_number, int var_value) { return setDeviceVariable(var_number, (byte) var_value); } public static byte[] setDeviceVariable(int var_number, byte var_value) { String req = "02 57 vn vv 10 03"; byte[] message = PrimareUtils.hexStringToByteArray(req.replaceAll(" ", "").toLowerCase()); message[2] = (byte) (var_number | 0x80); // OR with 0x80 required when setting variable message[3] = var_value; logger.debug(String.format("PrimareSPA20Message.setDeviceVariable %d (0x%02x) = %d (0x%02x), msg: %s", var_number, var_number, var_value, var_value, PrimareUtils.byteArrayToHex(message))); return message; } public static byte[] toggleDeviceVariable(int var_number) { String req = "02 57 vn 00 10 03"; byte[] message = PrimareUtils.hexStringToByteArray(req.replaceAll(" ", "").toLowerCase()); message[2] = (byte) var_number; logger.trace(String.format("PrimareSPA20Message.toggleDeviceVariable %d (0x%02x), msg: %s", var_number, var_number, PrimareUtils.byteArrayToHex(message))); return message; } public static byte[] queryDeviceVariable(int var_number) { String req = "02 52 vn 10 03"; byte[] message = PrimareUtils.hexStringToByteArray(req.replaceAll(" ", "").toLowerCase()); message[2] = (byte) var_number; logger.trace(String.format("PrimareSPA20Message.queryDeviceVariable %d (0x%02x), msg: %s", var_number, var_number, PrimareUtils.byteArrayToHex(message))); return message; } public static byte[] incDeviceVariable(int var_number) { return stepDeviceVariable(var_number, 1); } public static byte[] decDeviceVariable(int var_number) { return stepDeviceVariable(var_number, -1); } public static byte[] stepDeviceVariable(int var_number, int step) { String req = "02 57 vn st 10 03"; byte[] message = PrimareUtils.hexStringToByteArray(req.replaceAll(" ", "").toLowerCase()); message[2] = (byte) var_number; message[3] = (byte) step; logger.trace(String.format("PrimareSPA20Message.stepDeviceVariable %d (0x%02x), step:%d (0x%02x), msg: %s", var_number, var_number, step, step, PrimareUtils.byteArrayToHex(message))); return message; } }