def set_output(self, output_id, state, dimmer=None, timer=None): if output_id < 0 or output_id > 240: raise ValueError( 'Output ID {0} not in range 0 <= id <= 240'.format(output_id)) if dimmer is not None and dimmer < 0 or dimmer > 100: raise ValueError('Dimmer value {0} not in [0, 100]'.format(dimmer)) if timer is not None and timer not in [ 150, 450, 900, 1500, 2220, 3120 ]: raise ValueError( 'Timer value {0} not in [150, 450, 900, 1500, 2220, 3120]'. format(timer)) if dimmer is not None: master_version = self.get_firmware_version() if master_version >= (3, 143, 79): dimmer = int(0.63 * dimmer) self._master_communicator.do_command( master_api.write_dimmer(), { 'output_nr': output_id, 'dimmer_value': dimmer }) else: dimmer = int(dimmer) / 10 * 10 if dimmer == 0: dimmer_action = master_api.BA_DIMMER_MIN elif dimmer == 100: dimmer_action = master_api.BA_DIMMER_MAX else: dimmer_action = getattr( master_api, 'BA_LIGHT_ON_DIMMER_{0}'.format(dimmer)) self._master_communicator.do_command( master_api.basic_action(), { 'action_type': dimmer_action, 'action_number': output_id }) if not state: self._master_communicator.do_command(master_api.basic_action(), { 'action_type': master_api.BA_LIGHT_OFF, 'action_number': output_id }) return self._master_communicator.do_command(master_api.basic_action(), { 'action_type': master_api.BA_LIGHT_ON, 'action_number': output_id }) if timer is not None: timer_action = getattr( master_api, 'BA_LIGHT_ON_TIMER_{0}_OVERRULE'.format(timer)) self._master_communicator.do_command(master_api.basic_action(), { 'action_type': timer_action, 'action_number': output_id })
def test_do_command_passthrough(self): """ Test for the do_command with passthrough data. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock( [sin(action.create_input(1, in_fields)), sout("hello" + action.create_output(1, out_fields)), sin(action.create_input(2, in_fields)), sout(action.create_output(2, out_fields) + "world"), sin(action.create_input(3, in_fields)), sout("hello" + action.create_output(3, out_fields) + " world"), sin(action.create_input(4, in_fields)), sout("hello"), sout(action.create_output(4, out_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.enable_passthrough() comm.start() self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello", comm.get_passthrough_data()) self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("world", comm.get_passthrough_data()) self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello world", comm.get_passthrough_data()) self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello", comm.get_passthrough_data())
def test_background_consumer(self): """ Test the background consumer mechanism. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([ sout("OL\x00\x01\x03\x0c\r\n"), sin(action.create_input(1, in_fields)), sout("junkOL\x00\x02\x03\x0c\x05\x06\r\n here"), sout(action.create_output(1, out_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.enable_passthrough() got_output = {"phase": 1} def callback(output): """ Callback that check if the correct result was returned for OL. """ if got_output["phase"] == 1: self.assertEquals([(3, int(12 * 10.0 / 6.0))], output["outputs"]) got_output["phase"] = 2 elif got_output["phase"] == 2: self.assertEquals([(3, int(12 * 10.0 / 6.0)), (5, int(6 * 10.0 / 6.0))], output["outputs"]) got_output["phase"] = 3 comm.register_consumer(BackgroundConsumer(master_api.output_list(), 0, callback)) comm.start() self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals(3, got_output["phase"]) self.assertEquals("junk here", comm.get_passthrough_data())
def test_do_command_passthrough(self): """ Test for the do_command with passthrough data. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([ sin(action.create_input(1, in_fields)), sout("hello" + action.create_output(1, out_fields)), sin(action.create_input(2, in_fields)), sout(action.create_output(2, out_fields) + "world"), sin(action.create_input(3, in_fields)), sout("hello" + action.create_output(3, out_fields) + " world"), sin(action.create_input(4, in_fields)), sout("hello"), sout(action.create_output(4, out_fields)) ]) comm = MasterCommunicator(serial_mock, init_master=False) comm.enable_passthrough() comm.start() self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello", comm.get_passthrough_data()) self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("world", comm.get_passthrough_data()) self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello world", comm.get_passthrough_data()) self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello", comm.get_passthrough_data())
def toggle_output(self, output_id): if output_id < 0 or output_id > 240: raise ValueError('Output ID not in range 0 <= id <= 240: %d' % output_id) self._master_communicator.do_command(master_api.basic_action(), { 'action_type': master_api.BA_LIGHT_TOGGLE, 'action_number': output_id })
def test_watchdog(self): """ Test the watchdog. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} serial_mock = SerialMock([ sin(action.create_input(1, in_fields)), sin(action.create_input(2, in_fields)), sin(action.create_input(3, in_fields)) ]) timeout = False watchdog = {} def callback(): """ Callback for the watchdog """ watchdog['done'] = True comm = MasterCommunicator(serial_mock, init_master=False, watchdog_period=0.5, watchdog_callback=callback) comm.start() try: comm.do_command(action, in_fields, timeout=0.1) except CommunicationTimedOutException: timeout = True time.sleep(1) self.assertTrue(timeout) self.assertFalse('done' in watchdog) timeout = False try: comm.do_command(action, in_fields, timeout=0.1) except CommunicationTimedOutException: timeout = True self.assertTrue(timeout) timeout = False try: comm.do_command(action, in_fields, timeout=0.1) except CommunicationTimedOutException: timeout = True time.sleep(1.5) self.assertTrue(timeout) self.assertTrue('done' in watchdog)
def test_do_command(self): """ Test for standard behavior MasterCommunicator.do_command. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock( [sin(action.create_input(1, in_fields)), sout(action.create_output(1, out_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() output = comm.do_command(action, in_fields) self.assertEquals("OK", output["resp"])
def test_do_command_timeout(self): """ Test for timeout in MasterCommunicator.do_command. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} serial_mock = SerialMock([sin(action.create_input(1, in_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() try: comm.do_command(action, in_fields, timeout=0.1) self.assertTrue(False) except CommunicationTimedOutException: pass
def test_do_command_timeout(self): """ Test for timeout in MasterCommunicator.do_command. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} serial_mock = SerialMock([sin(action.create_input(1, in_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() try: comm.do_command(action, in_fields, timeout=0.1) self.assertTrue(False) except CommunicationTimedOutException: pass
def do_basic_action(self, action_type, action_number): """ Sends a basic action to the master with the given action type and action number :param action_type: The action type to execute :type action_type: int :param action_number: The action number to execute :type action_number: int :raises: :class`CommunicationTimedOutException` if master did not respond in time :raises: :class`InMaintenanceModeException` if master is in maintenance mode :returns: dict containing the output fields of the command """ logger.info('BA: Execute {0} {1}'.format(action_type, action_number)) return self.do_command(master_api.basic_action(), { 'action_type': action_type, 'action_number': action_number })
def test_do_command(self): """ Test for standard behavior MasterCommunicator.do_command. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([ sin(action.create_input(1, in_fields)), sout(action.create_output(1, out_fields)) ]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() output = comm.do_command(action, in_fields) self.assertEquals("OK", output["resp"])
def test_do_command_split_data(self): """ Test MasterCommunicator.do_command when the data is split over multiple reads. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} sequence = [] for i in range(1, 18): sequence.append(sin(action.create_input(i, in_fields))) output_bytes = action.create_output(i, out_fields) sequence.append(sout(output_bytes[:i])) sequence.append(sout(output_bytes[i:])) serial_mock = SerialMock(sequence) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() for i in range(1, 18): self.assertEquals("OK", comm.do_command(action, in_fields)["resp"])
def test_do_command_split_data(self): """ Test MasterCommunicator.do_command when the data is split over multiple reads. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} sequence = [] for i in range(1, 18): sequence.append(sin(action.create_input(i, in_fields))) output_bytes = action.create_output(i, out_fields) sequence.append(sout(output_bytes[:i])) sequence.append(sout(output_bytes[i:])) serial_mock = SerialMock(sequence) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() for i in range(1, 18): self.assertEquals("OK", comm.do_command(action, in_fields)["resp"])
def test_bytes_counter(self): """ Test the number of bytes written and read from the serial port. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock( [sin(action.create_input(1, in_fields)), sout("hello"), sout(action.create_output(1, out_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.enable_passthrough() comm.start() self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello", comm.get_passthrough_data()) self.assertEquals(21, comm.get_bytes_written()) self.assertEquals(5 + 18, comm.get_bytes_read())
def test_bytes_counter(self): """ Test the number of bytes written and read from the serial port. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([ sin(action.create_input(1, in_fields)), sout("hello"), sout(action.create_output(1, out_fields)) ]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals("hello", comm.get_passthrough_data()) self.assertEquals(21, comm.get_bytes_written()) self.assertEquals(5 + 18, comm.get_bytes_read())
def test_do_command_timeout_test_ongoing(self): """ Test if communication resumes after timeout. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([sin(action.create_input(1, in_fields)), sin(action.create_input(2, in_fields)), sout(action.create_output(2, out_fields))]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() try: comm.do_command(action, in_fields, timeout=0.1) self.assertTrue(False) except CommunicationTimedOutException: pass output = comm.do_command(action, in_fields) self.assertEquals("OK", output["resp"])
def test_background_consumer(self): """ Test the background consumer mechanism. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([ sout("OL\x00\x01\x03\x0c\r\n"), sin(action.create_input(1, in_fields)), sout("junkOL\x00\x02\x03\x0c\x05\x06\r\n here"), sout(action.create_output(1, out_fields)) ]) SetUpTestInjections(controller_serial=serial_mock) comm = MasterCommunicator(init_master=False) comm.enable_passthrough() got_output = {"phase": 1} def callback(output): """ Callback that check if the correct result was returned for OL. """ if got_output["phase"] == 1: self.assertEquals([(3, int(12 * 10.0 / 6.0))], output["outputs"]) got_output["phase"] = 2 elif got_output["phase"] == 2: self.assertEquals([(3, int(12 * 10.0 / 6.0)), (5, int(6 * 10.0 / 6.0))], output["outputs"]) got_output["phase"] = 3 comm.register_consumer( BackgroundConsumer(master_api.output_list(), 0, callback)) comm.start() self.assertEquals("OK", comm.do_command(action, in_fields)["resp"]) self.assertEquals(3, got_output["phase"]) self.assertEquals("junk here", comm.get_passthrough_data())
def test_do_command_timeout_test_ongoing(self): """ Test if communication resumes after timeout. """ action = master_api.basic_action() in_fields = {"action_type": 1, "action_number": 2} out_fields = {"resp": "OK"} serial_mock = SerialMock([ sin(action.create_input(1, in_fields)), sin(action.create_input(2, in_fields)), sout(action.create_output(2, out_fields)) ]) comm = MasterCommunicator(serial_mock, init_master=False) comm.start() try: comm.do_command(action, in_fields, timeout=0.1) self.assertTrue(False) except CommunicationTimedOutException: pass output = comm.do_command(action, in_fields) self.assertEquals("OK", output["resp"])
def test_output_has_crc(self): """ Test for MasterCommandSpec.output_has_crc. """ self.assertFalse(master_api.basic_action().output_has_crc()) self.assertTrue(master_api.read_output().output_has_crc())