Exemple #1
0
def leave():
    global seq
    tx(
        IEEE802154.IEEE802154(
            frame_type=IEEE802154.FRAME_TYPE_DATA,
            seq=seq,
            dst=0x0000,
            dst_pan=pan,
            src=nwk_addr,
            payload=ZigbeeNetwork.ZigbeeNetwork(
                aes=Parser.aes,
                frame_type=ZigbeeNetwork.FRAME_TYPE_CMD,
                version=2,
                radius=1,
                seq=12,
                dst=0xfffd,
                src=nwk_addr,
                ext_src=mac_addr,
                discover_route=0,
                security=1,
                sec_seq=bytearray(b'\x00\x00\x00\x00'),
                sec_key=1,
                sec_key_seq=0,
                payload=bytearray(b'\x04\x00')),
        ))
    seq += 1
Exemple #2
0
 def beacon(self):
     self.tx_ieee(
         IEEE802154.IEEE802154(
             frame_type=IEEE802154.FRAME_TYPE_CMD,
             command=IEEE802154.COMMAND_BEACON_REQUEST,
             seq=self.seq,
             src=None,
             src_pan=None,
             dst=0xFFFF,  # everyone
             dst_pan=0xFFFF,  # every PAN
             payload=b'',
         ))
Exemple #3
0
def loop():
	pan_set = False

	incoming = ''
	machine.zrepl(False)

	while True:
		pkt = Radio.rx()
		if pkt is not None:
			# throw away the extra b' and ' on the string
			# representation
			x = repr(hexlify(pkt))[2:-1]
			print(x)

			ieee = IEEE802154.IEEE802154(data=pkt)

			if ieee.frame_type == IEEE802154.FRAME_TYPE_CMD \
			and ieee.command == IEEE802154.COMMAND_JOIN_RESPONSE:
				# reponse to our join request; update our short address
				(new_nwk, status) = unpack("<HB", ieee.payload)
				if status == 0:
					print("NIC: NEW NWK %04x" % (new_nwk))
					Radio.address(new_nwk)
				else:
                                	print("NIC: NEW NWK failed")

			elif ieee.frame_type == IEEE802154.FRAME_TYPE_BEACON \
			and not pan_set \
			and ieee.payload[1] & 0x80 \
			and ieee.src != 0x0000:
				print("NIC: NEW PAN %04x" % (ieee.src_pan))                        
				Radio.pan(ieee.src_pan)
				pan_set = True

			x = None
			gc.collect()

		if machine.stdio_poll():
			y = sys.stdin.read(1)
			if y == '\r':
				continue
			if y != '\n':
				incoming += y
				continue
			#print("SEND:", incoming)
			try:
				x = unhexlify(incoming)
				Radio.tx(x)
			except:
				print("TX FAIL")
			incoming = ''
			x = None
			gc.collect()
Exemple #4
0
 def join(self, payload=b'\x80'):
     self.tx_ieee(
         IEEE802154.IEEE802154(
             frame_type=IEEE802154.FRAME_TYPE_CMD,
             command=IEEE802154.COMMAND_JOIN_REQUEST,
             ack_req=1,
             seq=self.seq,
             src=self.radio.mac(),
             src_pan=0xFFFF,  # not yet part of the PAN
             dst=self.router,
             dst_pan=self.radio.pan(),
             payload=
             payload,  # b'\x80' = Battery powered, please allocate address
         ))
     self.pending_data = True
     self.join_failed = False
Exemple #5
0
    def tx(self, payload, dst=None, ack_req=False, long_addr=False):
        pan = self.radio.pan()
        src = self.radio.address()
        if src is None:
            src = self.radio.mac()

        self.tx_ieee(
            IEEE802154.IEEE802154(
                frame_type=IEEE802154.FRAME_TYPE_DATA,
                dst=dst,
                dst_pan=pan,
                src=src,
                src_pan=pan,
                ack_req=ack_req,
                payload=payload,
            ))
Exemple #6
0
    def data_request(self):
        pan = self.radio.pan()
        src = self.radio.address()
        if src is None:
            src = self.radio.mac()

        self.tx_ieee(
            IEEE802154.IEEE802154(
                frame_type=IEEE802154.FRAME_TYPE_CMD,
                command=IEEE802154.COMMAND_DATA_REQUEST,
                dst=self.router,
                dst_pan=pan,
                src=src,
                src_pan=pan,
                ack_req=True,
            ))
Exemple #7
0
def data_request(src=None):
    global seq
    this_seq = seq
    seq += 1

    if src is None:
        src = nwk_addr

    return tx(
        IEEE802154.IEEE802154(
            frame_type=IEEE802154.FRAME_TYPE_CMD,
            command=IEEE802154.COMMAND_DATA_REQUEST,
            ack_req=True,
            seq=this_seq,
            src=src,
            dst=0x0000,
            dst_pan=pan,
            payload=b'',
        ))
Exemple #8
0
def wait_packet(wait_type):
    spins = 0
    ieee = IEEE802154.IEEE802154()
    while spins < max_spins:
        if reset_pin() == 0:
            break

        spins += 1
        b = Radio.rx()
        if b is None:
            continue
        # fast discard
        #print("b=", b[0])
        frame_type = b[0] & 0x7
        if frame_type != wait_type:
            continue
        ieee.deserialize(memoryview(b))
        print("<--", ieee)
        return ieee
    return None
Exemple #9
0
    def rx(self, data):
        if data is None or len(
                data) < 2:  # or len(data) < 2 or len(data) & 1 != 0:
            self.tick()
            return

        try:
            ieee = IEEE802154.IEEE802154(data=data)

            # check for duplicates, using the short address
            # long address duplicates will be processed
            if type(ieee.src) is int:
                if ieee.src in self.seqs \
                and self.seqs[ieee.src] == ieee.seq:
                    return

                self.seqs[ieee.src] = ieee.seq

            if self.verbose:
                print("RX: " + str(Parser.parse(data)[0]))

        except Exception as e:
            print("IEEE error: " + str(hexlify(data)))
            raise
            return

        if ieee.frame_type == IEEE802154.FRAME_TYPE_CMD:
            return self.handle_command(ieee)
        elif ieee.frame_type == IEEE802154.FRAME_TYPE_ACK:
            return self.handle_ack(ieee)
        elif ieee.frame_type == IEEE802154.FRAME_TYPE_BEACON:
            return self.handle_beacon(ieee)
        elif ieee.frame_type == IEEE802154.FRAME_TYPE_DATA:
            # for the next layer up, pass it to the handler
            return self.handler(ieee.payload)
        else:
            # should signal a wtf?
            print("RX: " + str(Parser.parse(data)[0]))
            pass
Exemple #10
0
from ZbPy import ZigbeeApplication
from ZbPy import ZigbeeCluster
from ZbPy import ZCL

import gc
gc.collect()

# This is the "well known" zigbee2mqtt key.
# The Ikea gateway uses a different key that has to be learned
# by joining the network (not yet implemented)
nwk_key = unhexlify(b"01030507090b0d0f00020406080a0c0d")
aes = AES.AES(nwk_key)

# Pre-allocate message types for the parser
# Only one message can be parsed at a time
ieee = IEEE802154.IEEE802154()
nwk = ZigbeeNetwork.ZigbeeNetwork(aes=aes)
aps = ZigbeeApplication.ZigbeeApplication()
zcl = ZigbeeCluster.ZigbeeCluster()
cmd = ZCL.ZCL()

# For filtering dupes
seqs = {}


def parse(data, verbose=False, filter_dupes=False):
    global seqs

    #print("------")
    #print(data)
    ieee.deserialize(data)
Exemple #11
0
 def ack(self, ack_seq):
     self.radio.tx(
         IEEE802154.IEEE802154(
             frame_type=IEEE802154.FRAME_TYPE_ACK,
             seq=ack_seq,
         ).serialize())
Exemple #12
0
def join():
    global seq
    global nwk_addr
    global pan
    gc.collect()

    Radio.promiscuous(1)

    pan = discover_pan()
    if pan is None:
        print("No PAN received?")
        return False

    print("PAN=0x%04x" % (pan))

    # Send the join request
    if not tx(
            IEEE802154.IEEE802154(
                frame_type=IEEE802154.FRAME_TYPE_CMD,
                command=IEEE802154.COMMAND_JOIN_REQUEST,
                seq=seq,
                src=mac_addr,
                src_pan=0xFFFF,
                dst=0x0000,
                dst_pan=pan,
                ack_req=True,
                payload=b'\x80',  # Battery powered, please allocate address
            )):
        print("JOIN_REQUEST: no ack")
        return False
    seq += 1

    if not data_request(src=mac_addr):
        print("DATA_REQUEST: long no ack")
        return False

    assoc = wait_packet(IEEE802154.FRAME_TYPE_CMD)
    if assoc is None:
        print("ASSOCIATE RESPONSE not received?")
        return False
    ack(assoc.seq)

    if assoc.command != IEEE802154.COMMAND_JOIN_RESPONSE:
        print("Not an associate response?")
        return False

    nwk_addr = (assoc.payload[0] << 0) | (assoc.payload[1] << 8)
    status = assoc.payload[2]

    if status == 2:
        print("JOIN DENIED!")
        return

    print("------------")
    print("New network address 0x%04x status %d" % (nwk_addr, status))
    gc.collect()
    return nwk_addr

    #Radio.promiscuous(0)
    #Radio.address(nwk_addr, pan)

    #if not data_request():
    #print("DATA_REQUEST: short no ack")

    # try to get the network key
    #for i in range(10):
    print("---- Sending request ----")
    if not data_request():
        print("DATA_REQUEST: short no ack")
    process_one()

    #print("Running loop")
    #loop(0)

    return True
Exemple #13
0
def ack(ack_seq):
    tx(IEEE802154.IEEE802154(frame_type=IEEE802154.FRAME_TYPE_ACK,
                             seq=ack_seq))
Exemple #14
0
    Radio.promiscuous(True)
    while True:
        if reset_pin() == 0:
            break

        bytes = Radio.rx()
        if bytes is None:
            continue
        # throw away the extra two bytes of wtf
        x = hexlify(bytes)
        print(x)


beacon_packet = IEEE802154.IEEE802154(frame_type=3,
                                      seq=99,
                                      command=7,
                                      dst=0xffff,
                                      dst_pan=0xffff)


def beacon():
    tx(beacon_packet)


def wait_packet(wait_type):
    spins = 0
    ieee = IEEE802154.IEEE802154()
    while spins < max_spins:
        if reset_pin() == 0:
            break