Ejemplo n.º 1
0
    def _fill_soft_ctx(self, start_pdu: bytes,
                       ctx: SoftContext) -> SoftContext:
        afk = start_pdu[0] & 0x40 >> 6
        aid = start_pdu[0] & 0x3f
        if afk == 1:
            app_name = self.__search_application_by_aid(aid)
            if not app_name:
                return None
            ctx.application_name = app_name
            ctx.is_devkey = False
        else:
            ctx.application_name = ''
            ctx.is_devkey = True

        return ctx
Ejemplo n.º 2
0
async def model_subscription_add(client_element: Element, target: str,
                                 model_id: bytes, addr: bytes) -> bool:
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')

    opcode = b'\x80\x1b'
    r_opcode = b'\x80\x1f'
    parameters = node_data.addr[::-1] + addr[::-1] + model_id[::-1]

    context = SoftContext(src_addr=b'\x00\x01', dst_addr=node_data.addr,
                          node_name=node_data.name,
                          network_name=node_data.network,
                          application_name='',
                          is_devkey=True, ack_timeout=3, segment_timeout=3)

    success = await client_element.send_message(opcode=opcode,
                                                parameters=parameters,
                                                ctx=context)
    if not success:
        return False

    r_content = await client_element.recv_message(opcode=r_opcode,
                                                  segment_timeout=1,
                                                  timeout=3, ctx=context)

    if r_content:
        if r_content[0] == 0 and r_content[1:] == parameters:
            return True

    return False
Ejemplo n.º 3
0
def send(target, opcode, parameters, devkey, app):
    '''Send a message to node'''

    click.echo(click.style(f'Sending message [{opcode}, {parameters}] to '
                           f'"{target}" node', fg='green'))
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')

    opcode = bytes.fromhex(opcode)
    parameters = bytes.fromhex(parameters)

    try:
        loop = asyncio.get_event_loop()
        client_element = Element()
        if devkey:
            app_name = ''
            is_devkey = True
        elif not node_data.apps:
            click.echo(click.style('Using devkey beacuse node hasn\'t '
                                   'application registred', fg='yellow'))
            app_name = ''
            is_devkey = True
        else:
            if app in node_data.apps:
                app_name = app
                is_devkey = False
            else:
                app_name = node_data.apps[0]
                is_devkey = False
        context = SoftContext(src_addr=b'\x00\x01',
                              dst_addr=node_data.addr,
                              node_name=node_data.name,
                              network_name=node_data.network,
                              application_name=app_name,
                              is_devkey=is_devkey,
                              ack_timeout=30,
                              segment_timeout=10)
        run_seq_t = run_seq([
            client_element.spwan_tasks(loop),
            client_element.send_message(opcode=opcode, parameters=parameters,
                                        ctx=context)
        ])
        loop.run_until_complete(run_seq_t)
    except KeyboardInterrupt:
        click.echo(click.style('Interruption by user', fg='yellow'))
    except RuntimeError:
        click.echo('Runtime error')
    except Exception as e:
        click.echo(f'Unknown error\n[{e}]')
    finally:
        client_element.disconnect()
        tasks_running = asyncio.Task.all_tasks()
        for t in tasks_running:
            t.cancel()
        loop.stop()

# 4d096b543184ab000000000000000000000000
# PublishTTL default 7 (4.3.2.16)
Ejemplo n.º 4
0
    async def recv_pdu(self):
        while True:
            self.log.debug(f'Waiting message...')
            msg_type, net_pdu = await self.recv_queue.get()

            # got a message from another channel
            if msg_type != b'message':
                continue

            # get network by nid
            nid = net_pdu[0] & 0x7f
            net_data = self.__search_network_by_nid(nid)
            if not net_data:
                continue

            # remove obsfucation
            clean_pdu = self._clean_message(net_pdu, net_data)

            # update seq, is_ctrl_msg
            self._fill_hard_ctx(clean_pdu)

            # decrypting
            src_addr = clean_pdu[-2:]
            mic_size = 8 if self.hard_ctx.is_ctrl_msg else 4
            net_mic = net_pdu[-mic_size:]
            encrypted_pdu = net_pdu[7:-mic_size]
            decrypted_pdu, mic_is_ok = self._decrypt(encrypted_pdu, src_addr,
                                                     net_data, net_mic)
            if not mic_is_ok:
                self.log.debug(f'Src addr: {src_addr.hex()}')
                self.log.debug(f'NetMIC wrong. Receive "{net_mic.hex()}"')
                continue

            # update seq number in node_data YAML file
            node_data = self.__search_node_by_addr(src_addr)
            if not node_data:
                self.log.debug(f'Node with addr {src_addr} is unknown')
                continue

            node_data.seq = self.hard_ctx.seq
            node_data.save()

            soft_ctx = SoftContext(src_addr=b'',
                                   dst_addr=b'',
                                   node_name='',
                                   network_name='',
                                   application_name='',
                                   is_devkey=False,
                                   ack_timeout=0,
                                   segment_timeout=0)
            soft_ctx.src_addr = src_addr
            soft_ctx.dst_addr = decrypted_pdu[0:2]
            soft_ctx.node_name = node_data.name
            soft_ctx.network_name = net_data.name

            transport_pdu = decrypted_pdu[2:]
            await self.transport_pdus.put(
                (transport_pdu, soft_ctx, self.hard_ctx.seq))
Ejemplo n.º 5
0
async def send_cmd(client_element: Element, target: str, opcode: bytes,
                   parameters: bytes, application: str):
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')

    app_name = application if application else node_data.apps[0]

    context = SoftContext(src_addr=b'\x00\x01', dst_addr=node_data.addr,
                          node_name=node_data.name,
                          network_name=node_data.network,
                          application_name=app_name,
                          is_devkey=False, ack_timeout=3, segment_timeout=3)

    success = await client_element.send_message(opcode=opcode,
                                                parameters=parameters,
                                                ctx=context)
    return success
Ejemplo n.º 6
0
async def appkey_add(client_element: Element, target: str,
                     application: str) -> bool:
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')
    app_data = ApplicationData.load(base_dir + app_dir + application + '.yml')
    net_data = NetworkData.load(base_dir + net_dir + app_data.network + '.yml')

    net_key = int.from_bytes(net_data.key_index, 'big')
    app_key = int.from_bytes(app_data.key_index, 'big')
    key_index = (net_key | (app_key << 12)).to_bytes(3, 'big')[::-1]

    opcode = b'\x00'
    r_opcode = b'\x80\x03'
    parameters = key_index + app_data.key

    context = SoftContext(src_addr=b'\x00\x01', dst_addr=node_data.addr,
                          node_name=node_data.name,
                          network_name=node_data.network,
                          application_name='',
                          is_devkey=True, ack_timeout=3, segment_timeout=3)

    success = await client_element.send_message(opcode=opcode,
                                                parameters=parameters,
                                                ctx=context)
    if not success:
        return False

    r_content = await client_element.recv_message(opcode=r_opcode,
                                                  segment_timeout=1,
                                                  timeout=3, ctx=context)

    if r_content:
        if r_content[0] == 0 and r_content[1:] == key_index:
            if app_data.name not in node_data.apps:
                node_data.apps.append(app_data.name)
                node_data.save()

            if node_data.name not in app_data.nodes:
                app_data.nodes.append(node_data.name)
                app_data.save()

            return True

    return False
Ejemplo n.º 7
0
async def model_publication_set(client_element: Element, target: str,
                                model_id: bytes, addr: bytes,
                                application: str) -> bool:
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')
    app_data = ApplicationData.load(base_dir + app_dir + application + '.yml')

    key_index = app_data.key_index
    default_ttl = b'\x07'
    period = b'\x00'
    default_xmit_int = b'\x40'

    opcode = b'\x03'
    r_opcode = b'\x80\x19'
    parameters = node_data.addr[::-1] + addr[::-1] + key_index[::-1] + \
        default_ttl[::-1] + period[::-1] + default_xmit_int[::-1] + \
        model_id[::-1]

    context = SoftContext(src_addr=b'\x00\x01', dst_addr=node_data.addr,
                          node_name=node_data.name,
                          network_name=node_data.network,
                          application_name='',
                          is_devkey=True, ack_timeout=3, segment_timeout=3)

    success = await client_element.send_message(opcode=opcode,
                                                parameters=parameters,
                                                ctx=context)
    if not success:
        return False

    r_content = await client_element.recv_message(opcode=r_opcode,
                                                  segment_timeout=1,
                                                  timeout=3, ctx=context)

    if r_content:
        if r_content[0] == 0 and r_content[1:] == parameters:
            return True

    return False
Ejemplo n.º 8
0
def add_appkey(target, app):
    '''Add a appkey to node'''

    click.echo(
        click.style(
            f'Add the appkey of "{app}" application to '
            f'"{target}" node',
            fg='green'))
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')
    app_data = ApplicationData.load(base_dir + app_dir + app + '.yml')
    net_data = NetworkData.load(base_dir + net_dir + node_data.network +
                                '.yml')

    net_key = int.from_bytes(net_data.key_index, 'big')
    app_key = int.from_bytes(app_data.key_index, 'big')
    key_index = (net_key | (app_key << 12)).to_bytes(3, 'big')[::-1]

    opcode = b'\x00'
    r_opcode = b'\x80\x03'
    parameters = key_index + app_data.key

    try:
        loop = asyncio.get_event_loop()
        client_element = Element()
        context = SoftContext(src_addr=b'\x00\x01',
                              dst_addr=node_data.addr,
                              node_name=node_data.name,
                              network_name=node_data.network,
                              application_name='',
                              is_devkey=True,
                              ack_timeout=10,
                              segment_timeout=3)
        run_seq_t = run_seq([
            client_element.spwan_tasks(loop),
            client_element.send_message(opcode=opcode,
                                        parameters=parameters,
                                        ctx=context),
            client_element.recv_message(opcode=r_opcode,
                                        segment_timeout=3,
                                        timeout=10,
                                        ctx=context)
        ])
        results = loop.run_until_complete(run_seq_t)

        content = results[2][0]
        if content:
            if content[0] == 0:
                if content[1:] == key_index:
                    click.echo(
                        click.style('App key add with successful', fg='green'))
                    if app_data.name not in node_data.apps:
                        node_data.apps.append(app_data.name)
                        node_data.save()

                    if node_data.name not in app_data.nodes:
                        app_data.nodes.append(node_data.name)
                        app_data.save()
                else:
                    click.echo(
                        click.style(f'Wrong key index: {content[1:].hex()}',
                                    fg='red'))
            else:
                click.echo(
                    click.style(f'Fail. Error code: {content[0:1].hex()}',
                                fg='red'))
    except KeyboardInterrupt:
        click.echo(click.style('Interruption by user', fg='yellow'))
    except RuntimeError:
        click.echo('Runtime error')
    except Exception:
        click.echo(traceback.format_exc())
    finally:
        client_element.disconnect()
        tasks_running = asyncio.Task.all_tasks()
        for t in tasks_running:
            t.cancel()
        loop.stop()
Ejemplo n.º 9
0
def req(target, opcode, parameters, r_opcode, devkey, app):
    '''Request a message to node (Send a message and wait the response)'''

    click.echo(
        click.style(
            f'Sending message [{opcode}, {parameters}] to '
            f'"{target}" node and wait receive a message with '
            f'opcode {r_opcode}',
            fg='green'))
    node_data = NodeData.load(base_dir + node_dir + target + '.yml')

    print(f'node addr: {node_data.addr}')

    opcode = bytes.fromhex(opcode)
    r_opcode = bytes.fromhex(r_opcode)
    parameters = bytes.fromhex(parameters)

    try:
        loop = asyncio.get_event_loop()
        client_element = Element()
        if devkey:
            app_name = ''
            is_devkey = True
        elif not node_data.apps:
            click.echo(
                click.style(
                    'Using devkey beacuse node hasn\'t '
                    'application registred',
                    fg='yellow'))
            app_name = ''
            is_devkey = True
        else:
            if app in node_data.apps:
                app_name = app
                is_devkey = False
            else:
                app_name = node_data.apps[0]
                is_devkey = False
        context = SoftContext(src_addr=b'\x00\x01',
                              dst_addr=node_data.addr,
                              node_name=node_data.name,
                              network_name=node_data.network,
                              application_name=app_name,
                              is_devkey=is_devkey,
                              ack_timeout=30,
                              segment_timeout=10)
        run_seq_t = run_seq([
            client_element.spwan_tasks(loop),
            client_element.send_message(opcode=opcode,
                                        parameters=parameters,
                                        ctx=context),
            client_element.recv_message(opcode=r_opcode,
                                        segment_timeout=3,
                                        timeout=10,
                                        ctx=context)
        ])
        results = loop.run_until_complete(run_seq_t)

        content = results[2][0]
        if content:
            click.echo(
                click.style(f'Message received: {content.hex()}', fg='white'))
        else:
            click.echo(
                click.style(
                    f'No message with opcode {r_opcode.hex()} '
                    f'received',
                    fg='red'))
    except KeyboardInterrupt:
        click.echo(click.style('Interruption by user', fg='yellow'))
    except RuntimeError:
        click.echo('Runtime error')
    except Exception as e:
        click.echo(f'Unknown error\n[{e}]')
    finally:
        client_element.disconnect()
        tasks_running = asyncio.Task.all_tasks()
        for t in tasks_running:
            t.cancel()
        loop.stop()