示例#1
0
class ConfigWriter(object):
    """A controller that applies configuration to a universe."""
    (DMX_START_ADDRESS, DEVICE_LABEL, PERSONALITY, COMPLETE) = range(4)

    def __init__(self, wrapper, pid_store):
        self.wrapper = wrapper
        self.pid_store = pid_store
        self.client = self.wrapper.Client()
        self.rdm_api = RDMAPI(self.client, self.pid_store)

    def Run(self, universe, configuration):
        """Run the collector.

    Args:
      universe: The universe to collect
      configuration: The config to apply
    """
        self.universe = universe
        self.configuration = configuration
        self.uids = list(configuration.keys())

        self.client.RunRDMDiscovery(self.universe, True, self._HandleUIDList)
        self.wrapper.Run()

    def _HandleUIDList(self, state, uids):
        """Called when the UID list arrives."""
        if not state.Succeeded():
            raise DiscoveryException(state.message)

        found_uids = set()
        for uid in uids:
            found_uids.add(uid)
            logging.debug(uid)

        for uid in self.configuration.keys():
            if uid not in found_uids:
                print('Device %s has been removed' % uid)
        self._SetNextUID()

    def _SetNextUID(self):
        """Start setting the info for the next UID."""
        if not self.uids:
            self.wrapper.Stop()
            return

        self.uid = self.uids.pop()
        print('Doing %s' % self.uid)
        self.work_state = self.DMX_START_ADDRESS
        self._NextState()

    def _NextState(self):
        """Move to the next state of information fetching."""
        if self.work_state == self.DMX_START_ADDRESS:
            address = self.configuration[self.uid].get('dmx_start_address')
            self.work_state = self.DEVICE_LABEL
            if address is not None:
                pid = self.pid_store.GetName('DMX_START_ADDRESS')
                self._SetPid(pid, [address])
                return

        if self.work_state == self.DEVICE_LABEL:
            label = self.configuration[self.uid].get('label')
            self.work_state = self.PERSONALITY
            if label is not None:
                pid = self.pid_store.GetName('DEVICE_LABEL')
                self._SetPid(pid, [label])
                return

        if self.work_state == self.PERSONALITY:
            personality = self.configuration[self.uid].get('personality')
            self.work_state = self.COMPLETE
            if personality is not None:
                pid = self.pid_store.GetName('DMX_PERSONALITY')
                self._SetPid(pid, [personality])
                return

        # this one is done, onto the next UID
        self._SetNextUID()

    def _SetPid(self, pid, values):
        self.rdm_api.Set(self.universe, self.uid, PidStore.ROOT_DEVICE, pid,
                         self._RDMRequestComplete, values)
        logging.debug('Sent %s request' % pid)
        self.outstanding_pid = pid

    def _RDMRequestComplete(self, response, unpacked_data, unpack_exception):
        if not response.status.Succeeded():
            print(response.status.message)
            self.wrapper.Stop()
            return

        if response.response_code != OlaClient.RDM_COMPLETED_OK:
            print(response.ResponseCodeAsString())
            self.wrapper.Stop()
            return

        if response.response_type == OlaClient.RDM_ACK_TIMER:
            # schedule the fetch
            logging.debug('Got ack timer for %d ms' % response.ack_timer)
            self.wrapper.AddEvent(response.ack_timer,
                                  self._FetchQueuedMessages)
            return

        # at this stage the response is either a ack or nack
        if response.response_type == OlaClient.RDM_NACK_REASON:
            print('Got nack with reason: %s' % response.nack_reason)
        self._NextState()
示例#2
0
    def testSetParamsWithNack(self):
        """uses client to send an RDM set with mocked olad.
    Regression test that confirms sent message is correct and
    sends fixed response message."""
        sockets = socket.socketpair()
        wrapper = ClientWrapper(sockets[0])
        pid_store = PidStore.GetStore(pid_store_path)
        client = wrapper.Client()
        rdm_api = RDMAPI(client, pid_store)

        class results:
            got_request = False
            got_response = False

        def DataCallback(self):
            # request and response for
            # ola_rdm_set.py -u 1 --uid 7a70:ffffff00 DMX_PERSONALITY 10
            # against olad dummy plugin
            # enable logging in rpc/StreamRpcChannel.py
            data = sockets[1].recv(4096)
            expected = binascii.unhexlify(
                "2b000010080110001a0a52444d436f6d6d616e6422190801120908f0f401150"
                "0ffffff180020e0012a010a30013800")
            self.assertEqual(data,
                             expected,
                             msg="Regression check failed. If protocol change "
                             "was intended set expected to: " +
                             str(binascii.hexlify(data)))
            results.got_request = True
            response = binascii.unhexlify(
                "2f0000100802100022290800100218002202000628e001300138004a0908f0f"
                "4011500ffffff520908f0f40115ac107de05831")
            sent_bytes = sockets[1].send(response)
            self.assertEqual(sent_bytes, len(response))

        def ResponseCallback(self, response, data, unpack_exception):
            results.got_response = True
            self.assertEqual(response.response_type, client.RDM_NACK_REASON)
            self.assertEqual(response.pid, 0xe0)
            self.assertEqual(response.nack_reason,
                             RDMNack.NR_DATA_OUT_OF_RANGE)
            wrapper.AddEvent(0, wrapper.Stop)

        wrapper._ss.AddReadDescriptor(sockets[1], lambda: DataCallback(self))

        uid = UID.FromString("7a70:ffffff00")
        pid = pid_store.GetName("DMX_PERSONALITY")
        rdm_api.Set(1,
                    uid,
                    0,
                    pid,
                    lambda x, y, z: ResponseCallback(self, x, y, z),
                    args=["10"])

        wrapper.Run()

        sockets[0].close()
        sockets[1].close()

        self.assertTrue(results.got_request)
        self.assertTrue(results.got_response)