示例#1
0
    def test_recs(self):
        proto = None
        calls = []

        def callback(success, msg, value):
            calls.append(msg)

        addr = IM.Address('0a.12.34')
        db = Mockdb(addr)
        handler = IM.handler.DeviceDbGet(db, callback)

        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        data = bytes([0x01, 0, 0, 0, 0, 0xFF, 0, 0x01, 0, 0, 0, 0, 0, 0])
        msg = Msg.InpExtended(addr, addr, flags, 0x2f, 0x00, data)

        r = handler.msg_received(proto, msg)
        assert r == Msg.CONTINUE
        assert len(calls) == 0

        msg.data = bytes(14)
        r = handler.msg_received(proto, msg)
        assert r == Msg.FINISHED
        assert len(calls) == 1
        assert calls[0] == "Database received"

        # no match
        msg.cmd1 = 0x00
        r = handler.msg_received(proto, msg)
        assert r == Msg.UNKNOWN
示例#2
0
    def test_handle_ext_flags(self, test_device):
        # Captured data from my own motion detector
        # 00 01 03 00 ff 0e 00 ff 0e 01 18 4f 00 d2
        # set as a 2842 model
        test_device.db.set_info(0x10, 0x01, 0x00)
        modem_addr = IM.Address(0x01, 0xAA, 0xFF)
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        msg = Msg.InpExtended(
            test_device.addr, modem_addr, flags, 0x2e, 0x00,
            bytes([
                0x00, 0x01, 0x03, 0x00, 0xff, 0x0e, 0x00, 0xff, 0x0e, 0x01,
                0x18, 0x4f, 0x00, 0xd2
            ]))

        def on_done(success, *args):
            assert success

        with mock.patch.object(IM.Signal, 'emit') as mocked:
            test_device.handle_ext_flags(msg, on_done)
            assert test_device.led_on
            assert test_device.night_only
            assert test_device.on_only
            assert test_device.battery_voltage_time > 0
            assert mocked.call_count == 1
            # the emit call should be false
            assert not mocked.call_args.args[1]
示例#3
0
    def test_recs(self):
        proto = None
        calls = []

        addr = IM.Address('0a.12.34')
        handler = IM.handler.DeviceGetDb(addr, calls.append)

        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        data = bytes([0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0, 0, 0])
        msg = Msg.InpExtended(addr, addr, flags, 0x2f, 0x00, data)

        r = handler.msg_received(proto, msg)
        assert r == Msg.CONTINUE
        assert len(calls) == 1
        assert calls[0] == msg

        msg.data = bytes(14)
        r = handler.msg_received(proto, msg)
        assert r == Msg.FINISHED
        assert len(calls) == 2
        assert calls[1] is None

        # no match
        msg.cmd1 = 0x00
        r = handler.msg_received(proto, msg)
        assert r == Msg.UNKNOWN
示例#4
0
 def test_handle_ext_flags(self, test_device):
     from_addr = IM.Address(0x01, 0x02, 0x05)
     flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
     data = bytes([0x01, 0x01, 0x00, 0x00, 0x20, 0x20, 0x1c, 0x1c, 0x1f,
                   0x00, 0x01, 0x00, 0x00, 0x00])
     msg = Msg.InpExtended(from_addr, test_device.addr, flags,
                           Msg.CmdType.EXTENDED_SET_GET, 0x00, data)
     def on_done(success, *args):
         assert success
     test_device.handle_ext_flags(msg, on_done)
     assert test_device.get_on_level() == 0x1C
示例#5
0
 def test_handle_ext_flags3(self, test_device, caplog):
     # set as a 2844 model
     test_device.db.set_info(0x10, 0x16, 0x00)
     modem_addr = IM.Address(0x01, 0xAA, 0xFF)
     flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
     msg = Msg.InpExtended(test_device.addr, modem_addr, flags,
                           0x2e, 0x00,
                           bytes([0x00, 0x01, 0x03, 0x00, 0xff, 0x0e, 0x00,
                                  0xff, 0x0e, 0x01, 0x18, 0x8C, 0x00, 0xd2])
                          )
     def on_done(success, *args):
         assert success
     with mock.patch.object(IM.Signal, 'emit') as mocked:
         test_device.handle_ext_flags(msg, on_done)
         assert test_device.led_on
         assert test_device.night_only
         assert test_device.on_only
         assert test_device.battery_voltage_time > 0
         assert mocked.call_count == 1
         # the emit call should be false, not a low battery for 2844
         assert not mocked.call_args.args[1]
示例#6
0
 def test_handle_ext_flags2(self, test_device):
     # This should trigger low battery
     test_device.battery_low_voltage = 8.0
     modem_addr = IM.Address(0x01, 0xAA, 0xFF)
     flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
     msg = Msg.InpExtended(test_device.addr, modem_addr, flags,
                           0x2e, 0x00,
                           bytes([0x00, 0x01, 0x03, 0x00, 0xff, 0x0e, 0x00,
                                  0xff, 0x0e, 0x01, 0x18, 0x4f, 0x00, 0xd2])
                          )
     def on_done(success, *args):
         assert success
     with mock.patch.object(IM.Signal, 'emit') as mocked:
         test_device.handle_ext_flags(msg, on_done)
         assert test_device.led_on
         assert test_device.night_only
         assert test_device.on_only
         assert test_device.battery_voltage_time > 0
         assert mocked.call_count == 1
         # the emit call should be true
         assert mocked.call_args.args[1]
示例#7
0
    def test_basic(self):
        obj = IM.db.Device()
        assert len(obj) == 0

        assert obj.is_current(0) is False
        obj.delta = 1
        assert obj.is_current(1) is True
        obj.clear_delta()
        assert obj.is_current(1) is False

        addr = IM.Address(0x10, 0xab, 0x1c)
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        db_flags = Msg.DbFlags(in_use=True, is_controller=True,
                               last_record=False)
        data = bytes([0x01, 0x02, 0x03])
        raw = [0x00, 0x01,
               0xfe, 0x10,  # mem_loc
               0x00, db_flags.to_bytes()[0],
               0x03,  # group
               addr.ids[0], addr.ids[1], addr.ids[2],
               data[0], data[1], data[2], 0x06]
        msg = Msg.InpExtended(addr, addr, flags, 0x00, 0x00, bytes(raw))
        obj.handle_db_rec(msg)

        # add same addr w/ different group
        raw[6] = 0x02
        msg.data = raw
        obj.handle_db_rec(msg)

        # new addr, same group
        addr2 = IM.Address(0x10, 0xab, 0x1d)
        raw[9] = 0x1d
        msg.data = raw
        obj.handle_db_rec(msg)

        # responder - not in a group
        db_flags = Msg.DbFlags(in_use=True, is_controller=False,
                               last_record=False)
        raw[5] = db_flags.to_bytes()[0]
        msg.data = raw
        obj.handle_db_rec(msg)

        # in use = False
        db_flags = Msg.DbFlags(in_use=False, is_controller=True,
                               last_record=False)
        raw[5] = db_flags.to_bytes()[0]
        msg.data = raw
        obj.handle_db_rec(msg)

        assert len(obj.entries) == 4
        assert len(obj.unused) == 1
        assert len(obj.groups) == 2

        grp = obj.find_group(0x02)
        assert len(grp) == 2
        assert grp[0].addr == addr
        assert grp[1].addr == addr2

        e = obj.find(addr, 0x02, 'CTRL')
        assert e.addr == addr
        assert e.group == 0x02
        assert e.db_flags.is_controller is True

        e = obj.find(addr2, 0x02, 'RESP')
        assert e.addr == addr2
        assert e.group == 0x02
        assert e.db_flags.is_responder is True

        e = obj.find(addr, 0x05, 'RESP')
        assert e is None

        str(obj)

        j = obj.to_json()
        obj2 = IM.db.Device.from_json(j)
        assert len(obj2.entries) == 4
        assert len(obj2.unused) == 1
        assert len(obj2.groups) == 2

        obj2.clear()
        assert len(obj2) == 0
        assert len(obj2.entries) == 0
        assert len(obj2.unused) == 0
        assert len(obj2.groups) == 0
示例#8
0
    def test_basic(self):
        obj = IM.db.Device(IM.Address(0x01, 0x02, 0x03))
        assert len(obj) == 0

        assert obj.is_current(0) is False
        obj.delta = 1
        assert obj.is_current(1) is True
        obj.set_delta(None)
        assert obj.is_current(1) is False

        assert obj.engine is None
        obj.set_engine(1)
        assert obj.engine == 1

        assert obj.desc is None
        assert obj.firmware is None
        obj.set_info(1, 2, 3)
        assert obj.desc.dev_cat == 1
        assert obj.desc.sub_cat == 2
        assert obj.firmware == 3

        addr = IM.Address(0x10, 0xab, 0x1c)
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        db_flags = Msg.DbFlags(in_use=True, is_controller=True,
                               is_last_rec=False)
        data = bytes([0x01, 0x02, 0x03])
        raw = [0x00, 0x01,
               0xfe, 0x10,  # mem_loc
               0x00, db_flags.to_bytes()[0],
               0x03,  # group
               addr.ids[0], addr.ids[1], addr.ids[2],
               data[0], data[1], data[2], 0x06]
        msg = Msg.InpExtended(addr, addr, flags, 0x00, 0x00, bytes(raw))
        entry = IM.db.DeviceEntry.from_bytes(msg.data)
        obj.add_entry(entry)

        # add same addr w/ different group
        raw[6] = 0x02
        raw[3] = 0x11  # have to change memory location
        msg.data = raw
        entry = IM.db.DeviceEntry.from_bytes(msg.data)
        obj.add_entry(entry)

        # new addr, same group
        addr2 = IM.Address(0x10, 0xab, 0x1d)
        raw[9] = 0x1d
        raw[3] = 0x12  # have to change memory location
        msg.data = raw
        entry = IM.db.DeviceEntry.from_bytes(msg.data)
        obj.add_entry(entry)

        # responder - not in a group
        db_flags = Msg.DbFlags(in_use=True, is_controller=False,
                               is_last_rec=False)
        raw[5] = db_flags.to_bytes()[0]
        raw[3] = 0x13  # have to change memory location
        msg.data = raw
        entry = IM.db.DeviceEntry.from_bytes(msg.data)
        obj.add_entry(entry)

        # in use = False
        db_flags = Msg.DbFlags(in_use=False, is_controller=True,
                               is_last_rec=False)
        raw[5] = db_flags.to_bytes()[0]
        raw[3] = 0x14  # have to change memory location
        msg.data = raw
        entry = IM.db.DeviceEntry.from_bytes(msg.data)
        obj.add_entry(entry)

        assert len(obj.entries) == 4
        assert len(obj.unused) == 1
        assert len(obj.groups) == 2

        grp = obj.find_group(0x02)
        assert len(grp) == 2
        assert grp[0].addr == addr
        assert grp[1].addr == addr2

        e = obj.find(addr, 0x02, True)
        assert e.addr == addr
        assert e.group == 0x02
        assert e.db_flags.is_controller is True

        e = obj.find(addr2, 0x02, False)
        assert e.addr == addr2
        assert e.group == 0x02
        assert e.db_flags.is_controller is False

        e = obj.find(addr, 0x05, False)
        assert e is None

        str(obj)

        j = obj.to_json()
        obj2 = IM.db.Device.from_json(j, '', None)
        assert len(obj2.entries) == 4
        assert len(obj2.unused) == 1
        assert len(obj2.groups) == 2

        obj2.clear()
        assert len(obj2) == 0
        assert len(obj2.entries) == 0
        assert len(obj2.unused) == 0
        assert len(obj2.groups) == 0
示例#9
0
    def test_cmd_from_msg(self):
        # Tests matching the command from the outbound message.
        proto = MockProto()
        calls = []

        def callback(msg, on_done=None):
            calls.append(msg)

        addr = IM.Address('0a.12.34')

        # sent message, match input command
        out = Msg.OutExtended.direct(addr,
                                     0x2e,
                                     0x00,
                                     bytes([0x00] * 2 + [0x01] + [0x00] * 11),
                                     crc_type="CRC")
        handler = IM.handler.ExtendedCmdResponse(out, callback)

        r = handler.msg_received(proto, "dummy")
        assert r == Msg.UNKNOWN

        # ack back.
        out.is_ack = False
        r = handler.msg_received(proto, out)
        assert r == Msg.CONTINUE

        # wrong cmd
        out.cmd1 = 0x13
        r = handler.msg_received(proto, out)
        assert r == Msg.UNKNOWN

        # wrong addr
        out.cmd1 = 0x11
        out.to_addr = IM.Address('0a.12.33')
        r = handler.msg_received(proto, out)
        assert r == Msg.UNKNOWN

        # Now pass in the input message.

        # expected input meesage
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x2e, 0x00)

        r = handler.msg_received(proto, msg)
        assert r == Msg.CONTINUE

        # wrong cmd
        msg.cmd1 = 0x13
        r = handler.msg_received(proto, msg)
        assert r == Msg.UNKNOWN

        # wrong addr
        msg.cmd1 = 0x11
        msg.from_addr = IM.Address('0a.12.33')
        r = handler.msg_received(proto, msg)
        assert r == Msg.UNKNOWN

        # direct NAK
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_NAK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x2e, 0x00)
        r = handler.msg_received(proto, msg)
        assert r == Msg.FINISHED

        # unexpected
        flags = Msg.Flags(Msg.Flags.Type.BROADCAST, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x2e, 0x00)
        r = handler.msg_received(proto, msg)
        assert r == Msg.UNKNOWN

        # Test receipt of extended payloads
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, False)
        msg = Msg.InpExtended(addr, addr, flags, 0x2e, 0x00,
                              bytes([0x00] * 14))
        r = handler.msg_received(proto, msg)
        assert r == Msg.FINISHED
        assert len(calls) == 1
        assert calls[0] == msg

        # Test receipt of bad payloads
        msg.from_addr = IM.Address('0a.12.33')
        r = handler.msg_received(proto, msg)
        assert r == Msg.UNKNOWN
示例#10
0
    def test_basic(self, tmpdir):
        protocol = MockProto()
        modem = MockModem(tmpdir)
        addr = IM.Address(0x01, 0x02, 0x03)
        thermo = Thermo(protocol, modem, addr)

        # setup signal tracking
        thermo.signal_ambient_temp_change.connect(
            self.handle_ambient_temp_change)
        thermo.signal_fan_mode_change.connect(self.handle_fan_mode_change)
        thermo.signal_mode_change.connect(self.handle_mode_change)
        thermo.signal_cool_sp_change.connect(self.handle_cool_sp_change)
        thermo.signal_heat_sp_change.connect(self.handle_heat_sp_change)
        thermo.signal_ambient_humid_change.connect(
            self.handle_ambient_humid_change)
        thermo.signal_status_change.connect(self.handle_status_change)
        thermo.signal_hold_change.connect(self.handle_hold_change)
        thermo.signal_energy_change.connect(self.handle_energy_change)

        # Lightly test pairing and I mean light.  Most of this testing is
        # handled by other tests
        thermo.pair()
        msg = Msg.OutStandard.direct(addr, 0x19, 0x00)
        test_msg = protocol.msgs.pop(0)
        assert test_msg.to_bytes() == msg.to_bytes()

        # test get_status
        thermo.get_status()
        msg = Msg.OutExtended.direct(addr,
                                     0x2e,
                                     0x02,
                                     bytes([0x00] * 14),
                                     crc_type="CRC")
        test_msg = protocol.msgs.pop(0)
        assert test_msg.to_bytes() == msg.to_bytes()

        # test handling of get_status response CELSIUS
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        msg = Msg.InpExtended(
            addr, addr, flags, 0x2e, 0x02,
            bytes([
                0x01, 0x04, 0x0a, 0x21, 0x05, 0x11, 0x1b, 0x1e, 0x00, 0xe0,
                0x88, 0x0e, 0x0f, 0xde
            ]))
        thermo.handle_status(msg, on_done=self.done)
        assert self.status == Thermo.Status.OFF
        assert self.hold is False
        assert self.energy is False
        assert self.fan == Thermo.Fan.ON
        assert self.mode == Thermo.Mode.AUTO
        assert self.humid == 30
        assert self.cool_sp == 27
        assert self.heat_sp == 14
        assert self.ambient == 22.4
        assert thermo.units == Thermo.CELSIUS

        # Test FARENHEIT
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        msg = Msg.InpExtended(
            addr, addr, flags, 0x2e, 0x02,
            bytes([
                0x01, 0x04, 0x0a, 0x21, 0x05, 0x11, 0x50, 0x1e, 0x00, 0xe0,
                0x80, 0x39, 0x0f, 0xde
            ]))
        thermo.handle_status(msg, on_done=self.done)
        assert round(self.cool_sp, 0) == 27
        assert round(self.heat_sp, 0) == 14
        assert self.ambient, 1 == 22.4
        assert thermo.units == Thermo.FARENHEIT

        # Test cooling w/ hold
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        msg = Msg.InpExtended(
            addr, addr, flags, 0x2e, 0x02,
            bytes([
                0x01, 0x04, 0x0a, 0x21, 0x05, 0x11, 0x50, 0x1e, 0x00, 0xe0,
                0x91, 0x39, 0x0f, 0xde
            ]))
        thermo.handle_status(msg, on_done=self.done)
        assert self.status == Thermo.Status.COOLING
        assert self.hold is True

        # Test heating w/ energy
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        msg = Msg.InpExtended(
            addr, addr, flags, 0x2e, 0x02,
            bytes([
                0x01, 0x04, 0x0a, 0x21, 0x05, 0x11, 0x50, 0x1e, 0x00, 0xe0,
                0x86, 0x39, 0x0f, 0xde
            ]))
        thermo.handle_status(msg, on_done=self.done)
        assert self.status == Thermo.Status.HEATING
        assert self.energy is True

        # Test bad status response
        flags = Msg.Flags(Msg.Flags.Type.DIRECT, True)
        msg = Msg.InpExtended(
            addr, addr, flags, 0x2e, 0x02,
            bytes([
                0x01, 0x04, 0x0a, 0x21, 0x05, 0xFF, 0x1b, 0x1e, 0x00, 0xe0,
                0x88, 0x0e, 0x0f, 0xde
            ]))
        thermo.handle_status(msg, on_done=self.done)

        # force a bad fan command, currently no way for this to happen
        # in the code, so just fake it here
        thermo.set_fan_mode_state(2)
        assert self.fan == Thermo.Fan.ON

        # test humidity setpoints, not enabled in code yet so this is just a
        # shell
        msg = Msg.OutExtended.direct(addr,
                                     0x2e,
                                     0x00,
                                     bytes([0x00] * 2 + [0x01] + [0x00] * 11),
                                     crc_type="CRC")
        thermo.get_humidity_setpoints()
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()
        thermo.handle_humidity_setpoints(msg)

        # Test enabling broadcast messages
        msg = Msg.OutExtended.direct(addr, 0x2e, 0x00,
                                     bytes([0x00] + [0x08] + [0x00] * 12))
        thermo.enable_broadcast()
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        thermo.handle_generic_ack(msg, on_done=self.done)

        # test thermo broadcast Messages
        flags = Msg.Flags(Msg.Flags.Type.ALL_LINK_BROADCAST, False)
        cool = IM.Address(0x00, 0x00, 0x01)
        msg = Msg.InpStandard(addr, cool, flags, 0x11, 0x00)
        thermo.handle_broadcast(msg)
        assert self.status == Thermo.Status.COOLING
        msg = Msg.InpStandard(addr, cool, flags, 0x13, 0x00)
        thermo.handle_broadcast(msg)
        assert self.status == Thermo.Status.OFF
        # test of bad group, shouldn't change status
        cool = IM.Address(0x00, 0x00, 0x07)
        msg = Msg.InpStandard(addr, cool, flags, 0x11, 0x00)
        thermo.handle_broadcast(msg)
        assert self.status == Thermo.Status.OFF
        # Test non-thermo broadcast
        cool = IM.Address(0x00, 0x00, 0x01)
        msg = Msg.InpStandard(addr, cool, flags, 0x20, 0x00)
        thermo.handle_broadcast(msg)

        # Test mode command
        msg = Msg.OutExtended.direct(addr, 0x6b, thermo.ModeCommands(0x04),
                                     bytes([0x00] * 14))
        thermo.mode_command(thermo.ModeCommands.HEAT)
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6b,
                              thermo.ModeCommands.HEAT.value)
        thermo.handle_mode_command(msg, on_done=self.done)
        assert self.mode == thermo.ModeCommands.HEAT
        # Test bad ack
        msg = Msg.InpStandard(addr, addr, flags, 0x6c,
                              thermo.ModeCommands.HEAT.value)
        thermo.handle_mode_command(msg, on_done=self.done)
        assert self.mode == thermo.ModeCommands.HEAT

        # Test fan command
        msg = Msg.OutExtended.direct(addr, 0x6b, thermo.FanCommands(0x07),
                                     bytes([0x00] * 14))
        thermo.fan_command(thermo.FanCommands.ON)
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6b,
                              thermo.FanCommands.ON.value)
        thermo.handle_fan_command(msg, on_done=self.done)
        assert self.fan == thermo.FanCommands.ON
        # Test bad ack
        msg = Msg.InpStandard(addr, addr, flags, 0x6c,
                              thermo.FanCommands.ON.value)
        thermo.handle_fan_command(msg, on_done=self.done)
        assert self.fan == thermo.FanCommands.ON

        # test heat setpoint command CELSIUS
        thermo.units = thermo.CELSIUS
        temp = 25
        msg = Msg.OutExtended.direct(addr, 0x6d, int(temp * 2),
                                     bytes([0x00] * 14))
        thermo.heat_sp_command(temp)
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        # test response handler
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6d, int(temp * 2))
        thermo.handle_heat_sp_command(msg, on_done=self.done)
        assert self.heat_sp == temp

        # Test FARENHEIT
        thermo.units = thermo.FARENHEIT
        temp_c = 25
        temp = (temp_c * 9 / 5) + 32
        msg = Msg.OutExtended.direct(addr, 0x6d, int(temp * 2),
                                     bytes([0x00] * 14))
        thermo.heat_sp_command(temp_c)
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        # test response handler
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6d, int(temp * 2))
        thermo.handle_heat_sp_command(msg, on_done=self.done)
        assert self.heat_sp == temp_c

        # BAd Ack
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6a, int(temp * 2))
        thermo.handle_heat_sp_command(msg, on_done=self.done)
        assert self.heat_sp == temp_c

        # test cool setpoint command CELSIUS
        thermo.units = thermo.CELSIUS
        temp = 25
        msg = Msg.OutExtended.direct(addr, 0x6c, int(temp * 2),
                                     bytes([0x00] * 14))
        thermo.cool_sp_command(temp)
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        # test response handler
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6c, int(temp * 2))
        thermo.handle_cool_sp_command(msg, on_done=self.done)
        assert self.cool_sp == temp

        # Test FARENHEIT
        thermo.units = thermo.FARENHEIT
        temp_c = 25
        temp = (temp_c * 9 / 5) + 32
        msg = Msg.OutExtended.direct(addr, 0x6c, int(temp * 2),
                                     bytes([0x00] * 14))
        thermo.cool_sp_command(temp_c)
        assert msg.to_bytes() == protocol.msgs.pop(0).to_bytes()

        # test response handler
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6c, int(temp * 2))
        thermo.handle_cool_sp_command(msg, on_done=self.done)
        assert self.cool_sp == temp_c

        # bad ack
        flags = Msg.Flags(Msg.Flags.Type.DIRECT_ACK, False)
        msg = Msg.InpStandard(addr, addr, flags, 0x6a, int(temp * 2))
        thermo.handle_cool_sp_command(msg, on_done=self.done)
        assert self.cool_sp == temp_c