Example #1
0
def S4_2_9_2_Test():
	"Serial interface guide s4.2.9.2 (page 23) test"
	# first test
	p, m = decode_packet('\\0538000108BAg', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert p.status_request == False
	assert p.application == 0x38
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], LightingOffSAL)
	assert p.sal[0].group_address == 8
	
	assert p.confirmation == 'g'
	
	assert m == None
	
	# second test
	p, m = decode_packet('\\05FF007A38004Ah', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert p.status_request == True
	assert p.application == 0x38
	assert p.group_address == 0
	assert p.confirmation == 'h'
	
	# no remainder
	assert m == None
Example #2
0
def pretty_packet(packet: bytes,
                  checksum: bool = True,
                  strict: bool = True,
                  server_packet: bool = True):
    packet, remainder = decode_packet(packet, checksum, strict, server_packet)

    print(packet)
Example #3
0
    def handle_data(self, buf: bytes) -> int:
        """
        Decodes a single CBus event and calls an event handler appropriate to
        the event.

        Do not override this.

        :param buf: CBus event data
        :type buf: bytes

        :returns: Number of bytes consumed from the buffer
        """
        logger.debug("Incoming data: %r", buf)

        p, remainder = decode_packet(buf,
                                     checksum=self.checksum,
                                     from_pci=not self.emulate_pci)

        if self.emulate_pci and remainder > 0:
            # Local echo
            self.echo(buf[:remainder])

        if p is not None:
            logger.debug("Got packet: %s", p)
            self.handle_cbus_packet(p)

        return remainder
Example #4
0
    def decode_packet(
            self,
            data: bytes,
            checksum: bool = True,
            strict: bool = True,
            from_pci: bool = True,
            expected_position: Optional[int] = None) -> Optional[BasePacket]:
        """
        Decodes a packet, and validates that the buffer position has consumed
        the packet.

        See ``cbus.packet.decode_packet`` for details.

        :param expected_position: If None (default), expect to consume the
                                  entire input data. Otherwise, an integer
                                  number of bytes that were expected to be
                                  consumed.
        :return: The parsed packet, or None if no packet was parsed.
        """
        if expected_position is None:
            expected_position = len(data)

        packet, position = decode_packet(data, checksum, strict, from_pci)
        self.assertEqual(
            expected_position, position,
            f'Expected to parse {expected_position} bytes of input data: '
            f'{data!r}')

        return packet
Example #5
0
def S9_1_Test():
	"Examples in quick start guide, s9.1"
	# turn on light 0x21
	p, r = decode_packet('\\053800792129i', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal), 1
	
	assert isinstance(p.sal[0], LightingOnSAL)
	assert p.sal[0].group_address, 0x21

	# check that it encodes properly again
	assert p.encode(), '053800792129'
	assert p.confirmation, 'i'
	
	# turn off light 0x21
	p, r = decode_packet('\\0538000121A1k', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], LightingOffSAL)
	assert p.sal[0].group_address == 0x21

	# check that it encodes properly again
	assert p.encode() == '0538000121A1'
	assert p.confirmation == 'k'
	
	# ramp light 0x21 to 50% over 4 seconds
	p, r = decode_packet('\\0538000A217F19l', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], LightingRampSAL)
	assert p.sal[0].group_address == 0x21
	assert p.sal[0].duration == 4
	# rounding must be done to 2 decimal places, as the value isn't actually
	# 50%, but 49.8039%.  next value is 50.1%.
	assert round(p.sal[0].level, 2) == 0.5
	
	# check that it encodes properly again
	assert p.encode() == '0538000A217F19'		
	assert p.confirmation == 'l'
Example #6
0
def S9_1_Test():
    "Examples in quick start guide, s9.1"
    # turn on light 0x21
    p, r = decode_packet('\\053800792129i', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal), 1

    assert isinstance(p.sal[0], LightingOnSAL)
    assert p.sal[0].group_address, 0x21

    # check that it encodes properly again
    assert p.encode(), '053800792129'
    assert p.confirmation, 'i'

    # turn off light 0x21
    p, r = decode_packet('\\0538000121A1k', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 1

    assert isinstance(p.sal[0], LightingOffSAL)
    assert p.sal[0].group_address == 0x21

    # check that it encodes properly again
    assert p.encode() == '0538000121A1'
    assert p.confirmation == 'k'

    # ramp light 0x21 to 50% over 4 seconds
    p, r = decode_packet('\\0538000A217F19l', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 1

    assert isinstance(p.sal[0], LightingRampSAL)
    assert p.sal[0].group_address == 0x21
    assert p.sal[0].duration == 4
    # rounding must be done to 2 decimal places, as the value isn't actually
    # 50%, but 49.8039%.  next value is 50.1%.
    assert round(p.sal[0].level, 2) == 0.5

    # check that it encodes properly again
    assert p.encode() == '0538000A217F19'
    assert p.confirmation == 'l'
Example #7
0
def issue2_test():
    "Handle the null lighting packet described in Issue #2."
    # lighting packet from the server, lighting application, source address 0x06
    # sometimes cbus units emit these null lighting commands because of an off-by-one issue?
    p, r = decode_packet('05063800BD')

    assert isinstance(p, PointToMultipointPacket)
    assert p.application == 0x38
    assert p.source_address == 0x06
    assert len(p.sal) == 0

    assert r == None
Example #8
0
def issue2_test():
	"Handle the null lighting packet described in Issue #2."
	# lighting packet from the server, lighting application, source address 0x06
	# sometimes cbus units emit these null lighting commands because of an off-by-one issue?
	p, r = decode_packet('05063800BD')
	
	assert isinstance(p, PointToMultipointPacket)
	assert p.application == 0x38
	assert p.source_address == 0x06
	assert len(p.sal) == 0
	
	assert r == None
Example #9
0
def Bennett_get_unit_type_test():
	"Example of 'get unit type' (identify type) from Geoffry Bennett's protocol reverse engineering docs"
	p, r = decode_packet('\\0699002101', server_packet=False, checksum=False)
	
	assert isinstance(p, PointToPointPacket), 'Packet is not PointToPointPacket'
	
	assert p.unit_address == 0x99
	assert len(p.cal) == 1
	
	assert isinstance(p.cal[0], IdentifyCAL)
	assert p.cal[0].attribute == 1
	
	assert p.encode() == '0699002101'
Example #10
0
def S9_2_Test():
    "Example in s9.2 (Serial Interface Guide) of decoding a reply CAL"
    p, r = decode_packet("8604990082300328", server_packet=True)
    assert isinstance(p, PointToPointPacket), "Packet is not PointToPointPacket"
    assert p.source_address == 4
    assert p.unit_address == 0x99
    assert len(p.cal) == 1

    assert isinstance(p.cal[0], ReplyCAL)
    assert p.cal[0].parameter == 0x30
    assert p.cal[0].data == "\x03"

    assert p.encode() == "8604990082300328"
Example #11
0
def S9_2_Test():
    "Example in s9.2 (Serial Interface Guide) of decoding a reply CAL"
    p, r = decode_packet('8604990082300328', server_packet=True)
    assert isinstance(p,
                      PointToPointPacket), 'Packet is not PointToPointPacket'
    assert p.source_address == 4
    assert p.unit_address == 0x99
    assert len(p.cal) == 1

    assert isinstance(p.cal[0], ReplyCAL)
    assert p.cal[0].parameter == 0x30
    assert p.cal[0].data == '\x03'

    assert p.encode() == '8604990082300328'
Example #12
0
def Bennett_get_unit_type_test():
    "Example of 'get unit type' (identify type) from Geoffry Bennett's protocol reverse engineering docs"
    p, r = decode_packet('\\0699002101', server_packet=False, checksum=False)

    assert isinstance(p,
                      PointToPointPacket), 'Packet is not PointToPointPacket'

    assert p.unit_address == 0x99
    assert len(p.cal) == 1

    assert isinstance(p.cal[0], IdentifyCAL)
    assert p.cal[0].attribute == 1

    assert p.encode() == '0699002101'
Example #13
0
def S2_11_Test():
	"Examples in Lighting Application s2.11"
	# switch on light at GA 0x93
	p, r = decode_packet('\\0538007993B7j', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], LightingOnSAL)
	assert p.sal[0].group_address == 0x93
	
	# check that it encodes properly again
	assert p.encode() == '0538007993B7'
	assert p.confirmation == 'j'
Example #14
0
def S2_11_Test():
    "Examples in Lighting Application s2.11"
    # switch on light at GA 0x93
    p, r = decode_packet('\\0538007993B7j', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 1

    assert isinstance(p.sal[0], LightingOnSAL)
    assert p.sal[0].group_address == 0x93

    # check that it encodes properly again
    assert p.encode() == '0538007993B7'
    assert p.confirmation == 'j'
Example #15
0
def S6_4_Test():
    "Examples in serial interface guide, s6.4"
    # Switch on light at GA 8
    p, r = decode_packet('\\0538000108BAg', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 1

    assert isinstance(p.sal[0], LightingOffSAL)
    assert p.sal[0].group_address == 8

    # check that it encodes properly again
    assert p.encode() == '0538000108BA'
    assert p.confirmation == 'g'

    # concatenated packet
    p, r = decode_packet('\\05380001087909090A25h', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 3

    # turn off light 8
    assert isinstance(p.sal[0], LightingOffSAL)
    assert p.sal[0].group_address == 8

    # turn on light 9
    assert isinstance(p.sal[1], LightingOnSAL)
    assert p.sal[1].group_address == 9

    # terminate ramp on light 10)
    assert isinstance(p.sal[2], LightingTerminateRampSAL)
    assert p.sal[2].group_address == 10

    # check that it encodes properly again
    assert p.encode() == '05380001087909090A25'
    assert p.confirmation == 'h'
Example #16
0
def S8_11_Test():
	"Example in enable control application guide, s8.11 (page 7)"
	# Set the network variable 0x37 to 0x82
	p, r = decode_packet('\\05CB0002378275g', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1

	assert isinstance(p.sal[0], EnableSetNetworkVariableSAL)
	assert p.sal[0].variable == 0x37
	assert p.sal[0].value == 0x82
	
	## check that it encodes properly again
	assert p.encode() == '05CB0002378275'
	assert p.confirmation == 'g'
Example #17
0
def S8_11_Test():
    "Example in enable control application guide, s8.11 (page 7)"
    # Set the network variable 0x37 to 0x82
    p, r = decode_packet('\\05CB0002378275g', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 1

    assert isinstance(p.sal[0], EnableSetNetworkVariableSAL)
    assert p.sal[0].variable == 0x37
    assert p.sal[0].value == 0x82

    ## check that it encodes properly again
    assert p.encode() == '05CB0002378275'
    assert p.confirmation == 'g'
Example #18
0
def S6_4_Test():
	"Examples in serial interface guide, s6.4"
	# Switch on light at GA 8
	p, r = decode_packet('\\0538000108BAg', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], LightingOffSAL)
	assert p.sal[0].group_address == 8
	
	# check that it encodes properly again
	assert p.encode() == '0538000108BA'
	assert p.confirmation == 'g'
	
	# concatenated packet
	p, r = decode_packet('\\05380001087909090A25h', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 3
	
	# turn off light 8
	assert isinstance(p.sal[0], LightingOffSAL)
	assert p.sal[0].group_address == 8
	
	# turn on light 9		
	assert isinstance(p.sal[1], LightingOnSAL)
	assert p.sal[1].group_address == 9
	
	# terminate ramp on light 10)
	assert isinstance(p.sal[2], LightingTerminateRampSAL)
	assert p.sal[2].group_address == 10
	
	# check that it encodes properly again
	assert p.encode() == '05380001087909090A25'
	assert p.confirmation == 'h'
Example #19
0
def S23_13_3_Test():
	"Example in s23.13.3 of decoding request refresh"
	# Request refreeh command
	# documentation is wrong here:
	#  - says      05DF00100C
	#  - should be 05DF00110308
	
	p, r = decode_packet('\\05DF00110308g', server_packet=False)
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], ClockRequestSAL)
	
	## check that it encodes properly again
	assert p.encode() == '05DF00110308'
	assert p.confirmation == 'g'
Example #20
0
def lighting_encode_decode_client_test():
    "self-made tests of encode then decode, with packets from a client."

    orig = PointToMultipointPacket(application=APP_LIGHTING)
    orig.sal.append(LightingOnSAL(orig, 27))

    data = orig.encode()

    d, r = decode_packet(data, server_packet=False)
    assert isinstance(orig, PointToMultipointPacket)
    assert len(orig.sal) == len(d.sal)

    assert isinstance(d.sal[0], LightingOnSAL)
    assert orig.sal[0].group_address == d.sal[0].group_address

    # ensure there is no remaining data to be parsed
    assert r == None
Example #21
0
def S9_11_Test():
    "Example in temperature broadcast application guide, s9.11"
    # Temperature of 25 degrees at group 5
    # note, the guide actually states that there is a checksum, but no
    # checksum is actually on the packet!
    p, r = decode_packet('\\05190002056477g', server_packet=False)

    assert isinstance(p, PointToMultipointPacket)
    assert len(p.sal) == 1

    assert isinstance(p.sal[0], TemperatureBroadcastSAL)
    assert p.sal[0].group_address == 5
    assert p.sal[0].temperature == 25

    ## check that it encodes properly again
    assert p.encode() == '05190002056477'
    assert p.confirmation == 'g'
Example #22
0
def lighting_encode_decode_client_test():
	"self-made tests of encode then decode, with packets from a client."
	
	orig = PointToMultipointPacket(application=APP_LIGHTING)
	orig.sal.append(LightingOnSAL(orig, 27))
	
	data = orig.encode()

	d, r = decode_packet(data, server_packet=False)
	assert isinstance(orig, PointToMultipointPacket)		
	assert len(orig.sal) == len(d.sal)
	
	assert isinstance(d.sal[0], LightingOnSAL)
	assert orig.sal[0].group_address == d.sal[0].group_address
	
	# ensure there is no remaining data to be parsed
	assert r == None
Example #23
0
def S9_11_Test():
	"Example in temperature broadcast application guide, s9.11"
	# Temperature of 25 degrees at group 5
	# note, the guide actually states that there is a checksum, but no
	# checksum is actually on the packet!
	p, r = decode_packet('\\05190002056477g', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1

	assert isinstance(p.sal[0], TemperatureBroadcastSAL)
	assert p.sal[0].group_address == 5
	assert p.sal[0].temperature == 25
	
	## check that it encodes properly again
	assert p.encode() == '05190002056477'
	assert p.confirmation == 'g'
Example #24
0
def S23_13_2_Test():
	"Example in s23.13.2 of decoding a date"
	# Set network date to 2005-02-25 (Friday)
	p, r = decode_packet('\\05DF000E0207D502190411g', server_packet=False)
	assert isinstance(p, PointToMultipointPacket)
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], ClockUpdateSAL)
	assert p.sal[0].is_date
	assert not p.sal[0].is_time
	assert isinstance(p.sal[0].val, date)
	
	assert p.sal[0].val.year == 2005
	assert p.sal[0].val.month == 2
	assert p.sal[0].val.day == 25
	assert p.sal[0].val.weekday() == 4 # friday

	## check that it encodes properly again
	assert p.encode() == '05DF000E0207D502190411'
	assert p.confirmation == 'g'
Example #25
0
def temperature_encode_decode_test():
    "self-made tests of encode then decode"

    orig = PointToMultipointPacket(application=APP_TEMPERATURE)
    orig.source_address = 5
    orig.sal.append(TemperatureBroadcastSAL(orig, 10, 0.5))
    orig.sal.append(TemperatureBroadcastSAL(orig, 11, 56))

    data = orig.encode()

    d, r = decode_packet(data)
    assert isinstance(orig, PointToMultipointPacket)
    assert orig.source_address == d.source_address
    assert len(orig.sal) == len(d.sal)

    for x in range(len(d.sal)):
        assert isinstance(d.sal[x], TemperatureBroadcastSAL)
        assert orig.sal[x].group_address == d.sal[x].group_address
        assert orig.sal[x].temperature == d.sal[x].temperature

    # ensure there is no remaining data to be parsed
    assert r == None
Example #26
0
def temperature_encode_decode_test():
	"self-made tests of encode then decode"
	
	orig = PointToMultipointPacket(application=APP_TEMPERATURE)
	orig.source_address = 5
	orig.sal.append(TemperatureBroadcastSAL(orig, 10, 0.5))
	orig.sal.append(TemperatureBroadcastSAL(orig, 11, 56))
	
	data = orig.encode()

	d, r = decode_packet(data)
	assert isinstance(orig, PointToMultipointPacket)		
	assert orig.source_address == d.source_address
	assert len(orig.sal) == len(d.sal)
	
	for x in range(len(d.sal)):
		assert isinstance(d.sal[x], TemperatureBroadcastSAL)
		assert orig.sal[x].group_address == d.sal[x].group_address
		assert orig.sal[x].temperature == d.sal[x].temperature
	
	# ensure there is no remaining data to be parsed
	assert r == None
Example #27
0
def S23_13_1_Test():
	"Example in s23.13.1 of decoding a time"
	# Set network time to 10:43:23 with no DST offset
	# Slight change from guide:
	p, r = decode_packet('\\05DF000D010A2B1700C2g', server_packet=False)
	
	assert isinstance(p, PointToMultipointPacket), "Packet is not PointToMultipointPacket"
	assert len(p.sal) == 1
	
	assert isinstance(p.sal[0], ClockUpdateSAL)
	assert p.sal[0].is_time
	assert not p.sal[0].is_date
	assert isinstance(p.sal[0].val, time)
	
	assert p.sal[0].val.hour == 10
	assert p.sal[0].val.minute == 43
	assert p.sal[0].val.second == 23
	
	# Library doesn't handle DST offset, so this flag is dropped.
	
	## check that it encodes properly again
	# fuzzy match to allow packet that has no DST information
	assert p.encode() in ['05DF000D010A2B1700C2', '05DF000D010A2B17FFC3']
	assert p.confirmation == 'g'
Example #28
0
def pretty_packet(packet, checksum=True, strict=True, server_packet=True):
    packet, remainder = decode_packet(packet, checksum, strict, server_packet)

    print packet
Example #29
0
	def decode_cbus_event(self, line):
		"""
		Decodes a CBus event and calls an event handler appropriate to the event.
		
		Do not override this.
		
		:param line: CBus event data
		:type line: str
		
		:returns: Remaining unparsed data (str) or None on error.
		:rtype: str or NoneType
		
		"""
		
		while line:
			last_line = line
			p, line = decode_packet(line, checksum=True, server_packet=True)
			
			if line == last_line:
				# infinite loop!
				log.msg('dce: bug: infinite loop detected on %r', line)
				return
			
			# decode special packets
			if p == None:
				log.msg("dce: packet == None")
				continue
			
			log.msg('dce: packet: %r' % p)
			
			if isinstance(p, SpecialServerPacket):
				if isinstance(p, PCIErrorPacket):
					self.on_pci_cannot_accept_data()
					continue
				elif isinstance(p, ConfirmationPacket):
					self.on_confirmation(p.code, p.success)
					continue
				
				log.msg('dce: unhandled SpecialServerPacket')
			elif isinstance(p, PointToMultipointPacket):
				for s in p.sal:
					if isinstance(s, LightingSAL):
						# lighting application
						if isinstance(s, LightingRampSAL):
							self.on_lighting_group_ramp(p.source_address, s.group_address, s.duration, s.level)
						elif isinstance(s, LightingOnSAL):
							self.on_lighting_group_on(p.source_address, s.group_address)
						elif isinstance(s, LightingOffSAL):
							self.on_lighting_group_off(p.source_address, s.group_address)
						elif isinstance(s, LightingTerminateRampSAL):
							self.on_lighting_group_terminate_ramp(p.source_address, s.group_address)
						else:
							log.msg('dce: unhandled lighting SAL type: %r', s)
							break
					elif isinstance(s, ClockSAL):
						if isinstance(s, ClockRequestSAL):
							self.on_clock_request(p.source_address)
						elif isinstance(s, ClockUpdateSAL):
							self.on_clock_update(p.source_address, s.variable, s.val)
					else:
						log.msg('dce: unhandled SAL type: %r', s)
						break
				
			else:
				log.msg('dce: unhandled other packet %r', p)
				continue
Example #30
0
def pretty_packet(packet, checksum=True, strict=True, server_packet=True):
	packet, remainder = decode_packet(packet, checksum, strict, server_packet)
	
	print packet
Example #31
0
	def decode_cbus_event(self, line):
		"""
		Decodes a CBus event and calls an event handler appropriate to the event.
		
		Do not override this.
		
		:param line: CBus event data
		:type line: str
		
		:returns: Remaining unparsed data (str) or None on error.
		:rtype: str or NoneType
		
		"""
		
		# pass the data to the protocol decoder
		p, remainder = decode_packet(line, checksum=self.checksum, server_packet=False)
		
		# check for special commands, and handle them.
		if p == None:
			log.msg("dce: packet == None")
			return remainder
			
		if isinstance(p, SpecialClientPacket):
			# do special things
			# full reset
			if isinstance(p, ResetPacket):
				self.on_reset()
				return remainder
			
			# smart+connect shortcut
			if isinstance(p, SmartConnectShortcutPacket):
				self.basic_mode = False
				self.checksum = True
				self.connect = True
				return remainder
				
			log.msg('dce: unknown SpecialClientPacket: %r', p)
		elif isinstance(p, PointToMultipointPacket):
			# is this a status inquiry
			
			if p.status_request == None:
				# status request
				# TODO
				log.msg('dce: unhandled status request packet')
			else:
				# application command
				
				for s in p.sal:
					if isinstance(s, LightingSAL):
						# lighting application
						if isinstance(s, LightingRampSAL):
							self.on_lighting_group_ramp(s.group_address, s.duration, s.level)
						elif isinstance(s, LightingOnSAL):
							self.on_lighting_group_on(s.group_address)
						elif isinstance(s, LightingOffSAL):
							self.on_lighting_group_off(s.group_address)
						elif isinstance(s, LightingTerminateRampSAL):
							self.on_lighting_group_terminate_ramp(s.group_address)
						else:
							log.msg('dce: unhandled lighting SAL type: %r' % s)
							return remainder
					elif isinstance(s, ClockSAL):
						if isinstance(s, ClockUpdateSAL):
							self.on_clock_update(s.variable, s.val)
						elif isinstance(s, ClockRequestSAL):
							self.on_clock_request()
						else:
							log.msg('dce: unhandled clock SAL type: %r' % s)
					else:
						log.msg('dce: unhandled SAL type: %r' % s)
						return remainder
		elif isinstance(p, DeviceManagementPacket):
			# TODO: send proper confirmation, from p55 of serial interface guide
			if p.parameter == 0x21:
				# application address 1
				application_addr1 = p.value
			elif p.parameter == 0x22:
				# application address 2
				application_addr2 = p.value
			elif p.parameter == 0x3E:
				# interface options 2
				# TODO: implement
				pass
			elif p.parameter == 0x42:
				# interface options 3
				# TODO: implement
				pass
			elif p.parameter in (0x30, 0x41):
				# interface options 1 / power up options 1
				self.connect = self.checksum = self.monitor = self.idmon = False
				self.basic_mode = True
				
				if p.value & 0x01:
					self.connect = True
				if p.value & 0x02:
					# reserved, ignored.
					pass
				if p.value & 0x04:
					# TODO: xon/xoff handshaking.  not supported.
					pass
				if p.value & 0x08:
					# srchk (checksum checking)
					self.checksum = True
				if p.value & 0x10:
					# smart mode
					self.basic_mode = False
					self.local_echo = False
				if p.value & 0x20:
					# monitor mode
					self.monitor = True
				if p.value & 0x40:
					# idmon
					self.idmon = True
			else:
				log.msg('dce: unhandled DeviceManagementPacket (%r = %r)' % (p.parameter, p.value))
				return remainder
		else:
			log.msg('dce: unhandled packet type: %r', p)
			return remainder
		
		# TODO: handle parameters
		
		if p.confirmation:
			self.send_confirmation(p.confirmation, True)
		
		return remainder
Example #32
0
    def decode_cbus_event(self, line):
        """
		Decodes a CBus event and calls an event handler appropriate to the event.
		
		Do not override this.
		
		:param line: CBus event data
		:type line: str
		
		:returns: Remaining unparsed data (str) or None on error.
		:rtype: str or NoneType
		
		"""

        while line:
            last_line = line
            p, line = decode_packet(line, checksum=True, server_packet=True)

            if line == last_line:
                # infinite loop!
                log.msg('dce: bug: infinite loop detected on %r', line)
                return

            # decode special packets
            if p == None:
                log.msg("dce: packet == None")
                continue

            log.msg('dce: packet: %r' % p)

            if isinstance(p, SpecialServerPacket):
                if isinstance(p, PCIErrorPacket):
                    self.on_pci_cannot_accept_data()
                    continue
                elif isinstance(p, ConfirmationPacket):
                    self.on_confirmation(p.code, p.success)
                    continue

                log.msg('dce: unhandled SpecialServerPacket')
            elif isinstance(p, PointToMultipointPacket):
                for s in p.sal:
                    if isinstance(s, LightingSAL):
                        # lighting application
                        if isinstance(s, LightingRampSAL):
                            self.on_lighting_group_ramp(
                                p.source_address, s.group_address, s.duration,
                                s.level)
                        elif isinstance(s, LightingOnSAL):
                            self.on_lighting_group_on(p.source_address,
                                                      s.group_address)
                        elif isinstance(s, LightingOffSAL):
                            self.on_lighting_group_off(p.source_address,
                                                       s.group_address)
                        elif isinstance(s, LightingTerminateRampSAL):
                            self.on_lighting_group_terminate_ramp(
                                p.source_address, s.group_address)
                        else:
                            log.msg('dce: unhandled lighting SAL type: %r', s)
                            break
                    elif isinstance(s, ClockSAL):
                        if isinstance(s, ClockRequestSAL):
                            self.on_clock_request(p.source_address)
                        elif isinstance(s, ClockUpdateSAL):
                            self.on_clock_update(p.source_address, s.variable,
                                                 s.val)
                    else:
                        log.msg('dce: unhandled SAL type: %r', s)
                        break

            else:
                log.msg('dce: unhandled other packet %r', p)
                continue