Exemplo n.º 1
0
    async def form_network(self,
                           channel=15,
                           pan_id=None,
                           extended_pan_id=None):
        channel = t.uint8_t(channel)

        if pan_id is None:
            pan_id = t.uint16_t.from_bytes(os.urandom(2), 'little')
        pan_id = t.uint16_t(pan_id)

        if extended_pan_id is None:
            extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8)

        initial_security_state = bellows.zigbee.util.zha_security(
            controller=True)
        v = await self._ezsp.setInitialSecurityState(initial_security_state)
        assert v[0] == t.EmberStatus.SUCCESS  # TODO: Better check

        parameters = t.EmberNetworkParameters()
        parameters.panId = pan_id
        parameters.extendedPanId = extended_pan_id
        parameters.radioTxPower = t.uint8_t(8)
        parameters.radioChannel = channel
        parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION
        parameters.nwkManagerId = t.EmberNodeId(0)
        parameters.nwkUpdateId = t.uint8_t(0)
        parameters.channels = t.uint32_t(0)

        await self._ezsp.formNetwork(parameters)
        await self._ezsp.setValue(t.EzspValueId.VALUE_STACK_TOKEN_WRITING, 1)
Exemplo n.º 2
0
async def _restore(ezsp,
                   backup_data,
                   force,
                   update_eui64_token=False,
                   upg_tc_link_key=False):
    """Restore backup."""

    (status, ) = await ezsp.networkInit()
    LOGGER.debug("Network init status: %s", status)
    assert status in (t.EmberStatus.SUCCESS, t.EmberStatus.NOT_JOINED)

    if status == t.EmberStatus.SUCCESS:
        if not force:
            click.echo("Network is up, not forcing restore")
            return
        try:
            (status, ) = await ezsp.leaveNetwork()
            if status != t.EmberStatus.NETWORK_DOWN:
                LOGGER.error("Couldn't leave network")
                return
        except asyncio.TimeoutError:
            LOGGER.error("Didn't not receive stack changed status callback")
            return

    if update_eui64_token:
        ncp_eui64 = t.EmberEUI64(backup_data[ATTR_NODE_EUI64]).serialize()
        (status, ) = await ezsp.setMfgToken(t.EzspMfgTokenId.MFG_CUSTOM_EUI_64,
                                            ncp_eui64)

    sec_bitmask = (t.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY
                   | t.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY
                   | t.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY
                   | t.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY
                   | t.EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET)
    if not is_well_known_key(backup_data[ATTR_KEY_GLOBAL][ATTR_KEY]):
        sec_bitmask |= t.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY

    init_sec_state = t.EmberInitialSecurityState(
        bitmask=sec_bitmask,
        preconfiguredKey=backup_data[ATTR_KEY_GLOBAL][ATTR_KEY],
        networkKey=backup_data[ATTR_KEY_NWK][ATTR_KEY],
        networkKeySequenceNumber=backup_data[ATTR_KEY_NWK][ATTR_KEY_SEQ],
        preconfiguredTrustCenterEui64=[0x00] * 8,
    )
    if (upg_tc_link_key
            and t.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY
            not in sec_bitmask):
        init_sec_state.bitmask |= (
            t.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY)
        init_sec_state.preconfiguredKey = t.EmberKeyData(os.urandom(16))

    (status, ) = await ezsp.setInitialSecurityState(init_sec_state)
    LOGGER.debug("Set initial security state: %s", status)
    assert status == t.EmberStatus.SUCCESS

    if backup_data[ATTR_KEY_TABLE]:
        await _restore_keys(ezsp, backup_data[ATTR_KEY_TABLE])

    network_key = backup_data[ATTR_KEY_NWK]
    (status, ) = await ezsp.setValue(
        ezsp.types.EzspValueId.VALUE_NWK_FRAME_COUNTER,
        t.uint32_t(network_key[ATTR_KEY_FRAME_COUNTER_OUT]).serialize(),
    )
    LOGGER.debug("Set network frame counter: %s", status)
    assert status == t.EmberStatus.SUCCESS

    tc_key = backup_data[ATTR_KEY_GLOBAL]
    (status, ) = await ezsp.setValue(
        ezsp.types.EzspValueId.VALUE_APS_FRAME_COUNTER,
        t.uint32_t(tc_key[ATTR_KEY_FRAME_COUNTER_OUT]).serialize(),
    )
    LOGGER.debug("Set network frame counter: %s", status)
    assert status == t.EmberStatus.SUCCESS

    await _form_network(ezsp, backup_data)
    await asyncio.sleep(2)
Exemplo n.º 3
0
def join(ctx, channels, pan_id, extended_pan_id):
    """Join an existing ZigBee network as an end device"""
    def cb(fut, frame_name, response):
        if frame_name == 'stackStatusHandler':
            fut.set_result(response)

    s = yield from util.setup(ctx.obj['device'], ctx.obj['baudrate'])

    channel = None

    if len(channels) != 1:
        if pan_id or extended_pan_id:
            raise click.BadOptionUsage(
                "Specify exactly one channel to join a specific network")
    else:
        channel = t.uint8_t(channels[0])

    if not (pan_id or extended_pan_id):
        scan_type = t.EzspNetworkScanType.ACTIVE_SCAN
        channel_mask = util.channel_mask(channels)
        click.echo("PAN not provided, scanning channels %s..." %
                   (' '.join(map(str, channels)), ))
        v = yield from s.startScan(scan_type, channel_mask, 3)

        networks = [n[0] for n in v if n[0].allowingJoin]
        if len(networks) == 0:
            click.echo("No joinable networks found")
            return 1
        if len(networks) > 1:
            click.echo("Multiple joinable networks found. Refusing to pick.")
            return 1

        network = networks[0]

        pan_id = network.panId
        extended_pan_id = network.extendedPanId
        channel = network.channel

        click.echo("Found network %s %s on channel %s" % (
            pan_id,
            extended_pan_id,
            channel,
        ))

    if pan_id is None:
        pan_id = t.uint16_t(0)
    else:
        pan_id = t.uint16_t(pan_id)
    if isinstance(extended_pan_id, str):
        extended_pan_id = util.parse_epan(extended_pan_id)
    if extended_pan_id is None:
        extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8)

    v = yield from util.network_init(s)

    if v[0] == t.EmberStatus.SUCCESS:
        LOGGER.debug("Network was up, leaving...")
        v = yield from s.leaveNetwork()
        util.check(v[0], "Failure leaving network: %s" % (v[0], ))
        yield from asyncio.sleep(1)  # TODO

    initial_security_state = zutil.zha_security()
    v = yield from s.setInitialSecurityState(initial_security_state)
    util.check(v[0], "Setting security state failed: %s" % (v[0], ))

    parameters = t.EmberNetworkParameters()
    parameters.extendedPanId = extended_pan_id
    parameters.panId = pan_id
    parameters.radioTxPower = t.uint8_t(8)
    parameters.radioChannel = t.uint8_t(channel)
    parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION
    parameters.nwkManagerId = t.EmberNodeId(0)
    parameters.nwkUpdateId = t.uint8_t(0)
    parameters.channels = t.uint32_t(0)
    click.echo(parameters)

    fut = asyncio.Future()
    cbid = s.add_callback(functools.partial(cb, fut))
    v = yield from s.joinNetwork(t.EmberNodeType.END_DEVICE, parameters)
    util.check(v[0], "Joining network failed: %s" % (v[0], ))
    v = yield from fut
    click.echo(v)

    s.remove_callback(cbid)

    s.close()
Exemplo n.º 4
0
def form(ctx, channel, pan_id, extended_pan_id):
    """Create a new ZigBee network"""
    s = yield from util.setup(ctx.obj['device'], util.print_cb)

    v = yield from util.networkInit(s)
    if v[0] == t.EmberStatus.SUCCESS:
        LOGGER.debug("Network was up, leaving...")
        v = yield from s.leaveNetwork()
        util.check(v[0], "Failure leaving network: %s" % (v[0], ))
        yield from asyncio.sleep(1)  # TODO

    initial_security_state = util.zha_security(controller=True)
    v = yield from s.setInitialSecurityState(initial_security_state)
    util.check(v[0], "Setting security state failed: %s" % (v[0], ))

    yield from util.basic_tc_permits(s)

    if channel:
        channel = t.uint8_t(channel)
    else:
        channel = t.uint8_t(17)

    if extended_pan_id:
        extended_pan_id = util.parse_epan(extended_pan_id)
    else:
        extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8)

    if pan_id:
        pan_id = t.uint16_t(pan_id)
    else:
        pan_id = t.uint16_t.from_bytes(os.urandom(2), 'little')

    parameters = t.EmberNetworkParameters()
    parameters.panId = pan_id
    parameters.extendedPanId = extended_pan_id
    parameters.radioTxPower = t.uint8_t(8)
    parameters.radioChannel = channel
    parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION
    parameters.nwkManagerId = t.EmberNodeId(0)
    parameters.nwkUpdateId = t.uint8_t(0)
    parameters.channels = t.uint32_t(0)
    click.echo(parameters)

    LOGGER.info("Forming network ...")
    fut = asyncio.Future()

    def cb(fut, frame_name, response):
        if frame_name == 'stackStatusHandler':
            fut.set_result(response)

    s.add_callback(functools.partial(cb, fut))
    v = yield from s.formNetwork(parameters)
    util.check(v[0], "Failed to form network: %s" % (v[0], ))

    v = yield from fut
    util.check(
        v[0],
        "Network didn't come up after form",
        t.EmberStatus.NETWORK_UP,
    )

    yield from s.setValue(t.EzspValueId.VALUE_STACK_TOKEN_WRITING, 1)
    yield from asyncio.sleep(0.1)

    s.close()