package it.angelic.soulissclient.model.typicals; import android.content.Context; import android.util.Log; import android.widget.TextView; import junit.framework.Assert; import java.util.ArrayList; import java.util.Calendar; import it.angelic.soulissclient.Constants; import it.angelic.soulissclient.HalfFloatUtils; import it.angelic.soulissclient.R; import it.angelic.soulissclient.SoulissApp; import it.angelic.soulissclient.helpers.SoulissPreferenceHelper; import it.angelic.soulissclient.model.ISoulissCommand; import it.angelic.soulissclient.model.ISoulissTypical; import it.angelic.soulissclient.model.ISoulissTypicalSensor; import it.angelic.soulissclient.model.SoulissTypical; import it.angelic.soulissclient.net.UDPHelper; import it.angelic.soulissclient.util.SoulissUtils; /** * Typical 31 : Temperature control with cooling and heating mode * <p/> * It compare an internal setpoint with a measured value to control a digital * output for cooling or heating. Actual temperature and desired setpoint are * stored and available for user interface or any other node in the network. * <p/> * <p/> * This typical use five (5) memory slot, arranged as follow: * <p/> * Temperature Control User Commands (IN / OUT) SLOT +0 * <p/> * Temperature Measured Value (IN / OUT) SLOT +1, SLOT +2 * <p/> * Temperature Setpoint Value (IN / OUT) SLOT +3, SLOT +4 * <p/> * all values shall be in half-precision floating point, automatic conversion is * done if using Souliss_AnalogIn * BIT 0 (0 System OFF, 1 System ON) * BIT 1 (0 Heating OFF , 1 Heating ON) * BIT 2 (0 Cooling OFF , 1 Cooling ON) * BIT 3 (0 Fan 1 OFF , 1 Fan 1 ON) * BIT 4 (0 Fan 2 OFF , 1 Fan 2 ON) * BIT 5 (0 Fan 3 OFF , 1 Fan 3 ON) * BIT 6 (0 Manual Mode , 1 Automatic Mode for Fan) * BIT 7 (0 Heating Mode, 1 Cooling Mode) * * @author shine@angelic.it */ public class SoulissTypical31Heating extends SoulissTypical implements ISoulissTypical, ISoulissTypicalSensor { // SoulissNode parentd = getParentNode(); // SoulissTypical TemperatureMeasuredValue = // parentd.getTypical((short)(getTypicalDTO().getSlot()+1)); /** * */ private static final long serialVersionUID = 1113488985342542012L; private float TemperatureMeasuredVal; private float TemperatureSetpointVal; //AUTOF public SoulissTypical31Heating(Context co, SoulissPreferenceHelper pp) { super(co, pp); } private void computeTempValues() { short TemperatureMeasuredValue = getParentNode().getTypical((short) (getTypicalDTO().getSlot() + 1)) .getTypicalDTO().getOutput(); short TemperatureMeasuredValue2 = getParentNode().getTypical((short) (getTypicalDTO().getSlot() + 2)) .getTypicalDTO().getOutput(); // Serve solo per dare comandi, da togliere SoulissTypical temperatureSetpointValue = getParentNode().getTypical((short) (getTypicalDTO().getSlot() + 3)); SoulissTypical temperatureSetpointValue2 = getParentNode().getTypical((short) (getTypicalDTO().getSlot() + 4)); short TemperatureSetpointValue = getParentNode().getTypical((short) (getTypicalDTO().getSlot() + 3)).getTypicalDTO().getOutput(); short TemperatureSetpointValue2 = getParentNode().getTypical((short) (getTypicalDTO().getSlot() + 4)).getTypicalDTO().getOutput(); // ora ho i due bytes, li converto int shifted = TemperatureMeasuredValue2 << 8; float celsius = HalfFloatUtils.toFloat(shifted + TemperatureMeasuredValue); TemperatureMeasuredVal = prefs.isFahrenheitChosen() ? SoulissUtils.celsiusToFahrenheit(celsius) : celsius; Log.i(Constants.TAG, "first:" + Long.toHexString((long) TemperatureMeasuredValue) + " second:" + Long.toHexString((long) TemperatureMeasuredValue2) + " SENSOR Reading:" + TemperatureMeasuredVal); // ora ho i due bytes, li converto int shifteds = TemperatureSetpointValue2 << 8; TemperatureSetpointVal = HalfFloatUtils.toFloat(shifteds + TemperatureSetpointValue); Log.i(Constants.TAG, "first:" + Long.toHexString((long) TemperatureSetpointValue) + " second:" + Long.toHexString((long) TemperatureSetpointValue2) + "SENSOR Setpoint:" + TemperatureSetpointVal); } @Override public ArrayList<ISoulissCommand> getCommands(Context ctx) { // ritorna le bozze dei comandi, da riempire con la schermata addProgram ArrayList<ISoulissCommand> ret = new ArrayList<>(); return ret; } @Override public String getOutputDesc() { if (Calendar.getInstance().getTime().getTime() - typicalDTO.getRefreshedAt().getTime().getTime() < (prefs.getDataServiceIntervalMsec() * 3)) { if (isStatusByteSet(getTypicalDTO().getOutput(), 0)) { if (isCoolMode()) return (context.getResources().getStringArray(R.array.HeatingFunction)[0]); else return (context.getResources().getStringArray(R.array.HeatingFunction)[1]); } else return context.getString(R.string.OFF); } else return context.getString(R.string.stale); } @Override public float getOutputFloat() { return TemperatureMeasuredVal; } @Override public String getTypedOutputValue() { computeTempValues(); /* * Log.d(Constants.TAG, "AirCon State: 0x" + * Integer.toHexString(typicalDTO.getOutput()) + " " + * Integer.toHexString * (TemperatureMeasuredValue.getTypicalDTO().getOutput())); */ StringBuilder strout = new StringBuilder(); // int fun = TemperatureMeasuredValue.getTypicalDTO().getOutput() >> 4; Log.i(Constants.TAG, "HEATING status: " + Integer.toBinaryString(getTypicalDTO().getOutput())); //final ByteBuffer buf = ByteBuffer.allocate(4); // sizeof(int) // buf.putInt(statusByte); /* BIT 0 (0 System OFF, 1 System ON) BIT 1 (0 Heating OFF , 1 Heating ON) BIT 2 (0 Cooling OFF , 1 Cooling ON) BIT 3 (0 Fan 1 OFF , 1 Fan 1 ON) BIT 4 (0 Fan 2 OFF , 1 Fan 2 ON) BIT 5 (0 Fan 3 OFF , 1 Fan 3 ON) BIT 6 (0 Manual Mode , 1 Automatic Mode for Fan) BIT 7 (0 Heating Mode, 1 Cooling Mode) */ if (isTurnedOn()) { if (isCoolMode()) strout.append("COOL"); else strout.append("HEAT"); } else strout.append("OFF"); if (isStatusByteSet(getTypicalDTO().getOutput(), 6)) strout.append(" - Fan Auto"); else strout.append(" - Fan Manual"); strout.append(" ").append(String.format("%.2f", TemperatureMeasuredVal)).append("°").append(prefs.isFahrenheitChosen() ? "F" : "C") .append(" (").append(String.format("%.2f", TemperatureSetpointVal)).append("°").append(prefs.isFahrenheitChosen() ? "F" : "C").append(")"); return strout.toString(); } public float getTemperatureMeasuredVal() { computeTempValues(); return TemperatureMeasuredVal; } public float getTemperatureSetpointVal() { computeTempValues(); return TemperatureSetpointVal; } public boolean isCoolMode() { return isStatusByteSet(getTypicalDTO().getOutput(), 7); } public boolean isFannTurnedOn(int fan) { if (fan < 1 || fan > 3) return false; //fan start from return isStatusByteSet(getTypicalDTO().getOutput(), 2 + fan); } private boolean isHeatMode() { return !isCoolMode(); } private boolean isStatusByteSet(int b, int n) { return ((b & (1L << n)) != 0); } public boolean isTurnedOn() { return isStatusByteSet(getTypicalDTO().getOutput(), 0); } public void issueCommand(final int function, final Float temp) { Thread t = new Thread() { public void run() { if (temp == null) { Log.i(Constants.TAG, "ISSUE COMMAND W/O TEMP:" + String.valueOf((float) function)); UDPHelper.issueSoulissCommand("" + getParentNode().getNodeId(), "" + getTypicalDTO().getSlot(), SoulissApp.getOpzioni(), "" + function); } else { int re = HalfFloatUtils.fromFloat(temp); String first, second; String pars = Long.toHexString(re); Log.i(Constants.TAG, "PARSED SETPOINT TEMP: 0x" + pars); try { second = Integer.toString(Integer.parseInt(pars.substring(0, 2), 16)); } catch (StringIndexOutOfBoundsException sie) { second = "0"; } try { first = Integer.toString(Integer.parseInt(pars.substring(2, 4), 16)); } catch (StringIndexOutOfBoundsException sie) { first = "0"; } //INVERTITI? Occhio String[] cmd = {String.valueOf(function), "0", "0", first, second}; //verifyCommand(temp, first, second); Log.i(Constants.TAG, "ISSUE COMMAND:" + String.valueOf(function) + " 0 0 " + first + " " + second); UDPHelper.issueSoulissCommand("" + getParentNode().getNodeId(), "" + getTypicalDTO().getSlot(), SoulissApp.getOpzioni(), cmd); } } }; t.start(); } @Override public void setOutputDescView(TextView textStatusVal) { textStatusVal.setText(getOutputDesc()); if ((typicalDTO.getOutput() == 0 || typicalDTO.getOutput() >> 6 == 1) || !isTurnedOn() || UNKNOWN.compareTo(getTypedOutputValue()) == 0 || NOT_AVAILABLE.compareTo(getTypedOutputValue()) == 0) { textStatusVal.setTextColor(context.getResources().getColor(R.color.std_red)); textStatusVal.setBackgroundResource(R.drawable.borderedbackoff); } else { textStatusVal.setTextColor(context.getResources().getColor(R.color.std_green)); textStatusVal.setBackgroundResource(R.drawable.borderedbackon); } } //TODO move in tests private void verifyCommand(Float toSend, String byteOne, String byteTwo) { int re = HalfFloatUtils.fromFloat(toSend); String pars = Long.toHexString(re); Log.d(Constants.TAG, "SetPoint" + toSend + ", in HEX:" + pars); String first = Integer.toString(Integer.parseInt(pars.substring(0, 2), 16)); String second = Integer.toString(Integer.parseInt(pars.substring(2, 4), 16)); Log.d(Constants.TAG, "Splitted (DEC) - first:" + first + " - second:" + second); short TemperatureMeasuredValueShift = Short.parseShort(first); short TemperatureMeasuredValue = Short.parseShort(second); int shifted = TemperatureMeasuredValueShift << 8; float reconv = HalfFloatUtils.toFloat(shifted + TemperatureMeasuredValue); Log.d(Constants.TAG, "Reconverted:" + reconv); Assert.assertTrue(byteOne.equals(first)); Assert.assertTrue(byteTwo.equals(second)); } }