Skip to content

Commit

Permalink
Create new Packet -type, UTETeachIn to fix issue #13.
Browse files Browse the repository at this point in the history
- Currently parses an incoming teach-in request from D2-01-01.
- Still requires a response packet creation.
  • Loading branch information
kipe committed Feb 15, 2016
1 parent fc1cbfe commit 62ee217
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 3 deletions.
34 changes: 34 additions & 0 deletions enocean/protocol/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class RORG(IntEnum):
SYS_EX = 0xC5
SEC = 0x30
SEC_ENCAPS = 0x31
UTE = 0xD4


# Results for message parsing
Expand Down Expand Up @@ -103,3 +104,36 @@ class DB3:
BIT_5 = -30
BIT_6 = -31
BIT_7 = -32


class DB4:
BIT_0 = -33
BIT_1 = -34
BIT_2 = -35
BIT_3 = -36
BIT_4 = -37
BIT_5 = -38
BIT_6 = -39
BIT_7 = -40


class DB5:
BIT_0 = -41
BIT_1 = -42
BIT_2 = -43
BIT_3 = -44
BIT_4 = -45
BIT_5 = -46
BIT_6 = -47
BIT_7 = -48


class DB6:
BIT_0 = -49
BIT_1 = -50
BIT_2 = -51
BIT_3 = -52
BIT_4 = -53
BIT_5 = -54
BIT_6 = -55
BIT_7 = -56
60 changes: 57 additions & 3 deletions enocean/protocol/packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import enocean.utils
from enocean.protocol import crc8
from enocean.protocol.eep import EEP
from enocean.protocol.constants import PACKET, RORG, PARSE_RESULT, DB0, DB2, DB3
from enocean.protocol.constants import PACKET, RORG, PARSE_RESULT, DB0, DB2, DB3, DB4, DB6

logger = logging.getLogger('enocean.protocol.packet')

Expand Down Expand Up @@ -48,7 +48,9 @@ def _bit_data(self):
if self.rorg == RORG.RPS or self.rorg == RORG.BS1:
return enocean.utils.to_bitarray(self.data[1], 8)
if self.rorg == RORG.BS4:
return enocean.utils.to_bitarray(self.data[1:5], 32)
return enocean.utils.to_bitarray(self.data[1:5], 4 * 8)
if self.rorg == RORG.UTE:
return enocean.utils.to_bitarray(self.data[1:8], 7 * 8)

@_bit_data.setter
def _bit_data(self, value):
Expand All @@ -57,6 +59,9 @@ def _bit_data(self, value):
if self.rorg == RORG.BS4:
for byte in range(4):
self.data[byte+1] = enocean.utils.from_bitarray(value[byte*8:(byte+1)*8])
if self.rorg == RORG.UTE:
for byte in range(7):
self.data[byte+1] = enocean.utils.from_bitarray(value[byte*8:(byte+1)*8])

# # COMMENTED OUT, AS NOTHING TOUCHES _bit_optional FOR NOW.
# # Thus, this is also untested.
Expand Down Expand Up @@ -131,7 +136,11 @@ def parse_msg(buf):

# If we got this far, everything went ok (?)
if packet_type == PACKET.RADIO:
p = RadioPacket(packet_type, data, opt_data)
# Need to handle UTE Teach-in here, as it's a separate packet type...
if data[0] == RORG.UTE:
p = UTETeachIn(packet_type, data, opt_data)
else:
p = RadioPacket(packet_type, data, opt_data)
elif packet_type == PACKET.RESPONSE:
p = ResponsePacket(packet_type, data, opt_data)
else:
Expand Down Expand Up @@ -305,6 +314,51 @@ def parse(self):
return super(RadioPacket, self).parse()


class UTETeachIn(RadioPacket):
# Request types
TEACH_IN = 0b00
DELETE = 0b01
NOT_SPECIFIC = 0b10

# Response types
NOT_ACCEPTED = 0b00
TEACHIN_ACCEPTED = 0b01
DELETE_ACCEPTED = 0b10
EEP_NOT_SUPPORTED = 0b11

unidirectional = False
response_expected = False
number_of_channels = 0xFF
rorg_of_eep = RORG.UNDEFINED
request_type = NOT_SPECIFIC

@property
def bidirectional(self):
return not self.unidirectional

@property
def teach_in(self):
return self.request_type != self.DELETE

@property
def delete(self):
return self.request_type == self.DELETE

def parse(self):
super(UTETeachIn, self).parse()
self.unidirectional = not self._bit_data[DB6.BIT_7]
self.response_expected = not self._bit_data[DB6.BIT_6]
self.request_type = enocean.utils.from_bitarray(self._bit_data[DB6.BIT_5:DB6.BIT_3])
self.rorg_manufacturer = enocean.utils.from_bitarray(self._bit_data[DB3.BIT_2:DB2.BIT_7] + self._bit_data[DB4.BIT_7:DB3.BIT_7])
self.rorg_type = self.data[5]
self.rorg_func = self.data[6]
self.rorg_of_eep = self.data[7]
return self.parsed

def create_response(self, accepted=True, not_accepted_reason=EEP_NOT_SUPPORTED):
pass


class ResponsePacket(Packet):
response = 0
response_data = []
Expand Down
28 changes: 28 additions & 0 deletions tests/test_teachin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- encoding: utf-8 -*-
from __future__ import print_function, unicode_literals, division

from enocean.protocol.packet import Packet
from enocean.protocol.constants import RORG


def test_ute():
# ['0xd4', '0xa0', '0xff', '0x3e', '0x0', '0x1', '0x1', '0xd2', '0x1', '0x94', '0xe3', '0xb9', '0x0'] ['0x1', '0xff', '0xff', '0xff', '0xff', '0x40', '0x0']
status, buf, p = Packet.parse_msg(bytearray([
0x55,
0x00, 0x0D, 0x07, 0x01,
0xFD,
0xD4, 0xA0, 0xFF, 0x3e, 0x00, 0x01, 0x01, 0xD2, 0x01, 0x94, 0xE3, 0xB9, 0x00,
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00,
0xAB
]))
assert p.sender_hex == '01:94:E3:B9'
assert p.unidirectional is False
assert p.bidirectional is True
assert p.response_expected is True
assert p.number_of_channels == 0xFF
assert p.rorg_manufacturer == 0x3E
assert p.rorg_of_eep == RORG.VLD
assert p.rorg_func == 0x01
assert p.rorg_type == 0x01
assert p.teach_in is True
assert p.delete is False

0 comments on commit 62ee217

Please sign in to comment.