Skip to content

Commit

Permalink
tv-casting-app: Support for pre-commissioned state to Discovered Vide…
Browse files Browse the repository at this point in the history
…o Player Nodes, new AppParams and Read Attribute APIs (project-chip#23303)

* tv-casting-app: Support to pass in the new AppParameters (includes rotatingDeviceId)

* tv-casting-app: Adding Read API for ApplicationBasic cluster

* tv-casting-app: Exposing pre commissioned state and toConnectableVideoPlayer API
  • Loading branch information
sharadb-amazon committed Nov 11, 2022
1 parent 2bc1a54 commit d0a3d57
Show file tree
Hide file tree
Showing 43 changed files with 1,682 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ public String getCommissionerButtonText(DiscoveredNodeData commissioner) {
? (aux.isEmpty() ? "" : " from ") + "Vendor ID: " + commissioner.getVendorId()
: "";
aux = aux.isEmpty() ? aux : "\n[" + aux + "]";
return main + aux;

String preCommissioned = commissioner.isPreCommissioned() ? " (Pre-commissioned)" : "";
return main + aux + preCommissioned;
}

/** Interface for notifying the host. */
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package com.chip.casting.app;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.chip.casting.ContentApp;
import com.chip.casting.DiscoveredNodeData;
import com.chip.casting.FailureCallback;
import com.chip.casting.MatterCallbackHandler;
import com.chip.casting.MatterError;
import com.chip.casting.SuccessCallback;
import com.chip.casting.TvCastingApp;
import com.chip.casting.VideoPlayer;
import com.chip.casting.util.GlobalCastingConstants;

/** A {@link Fragment} to get the TV Casting App commissioned / connected. */
public class ConnectionFragment extends Fragment {
private static final String TAG = ConnectionFragment.class.getSimpleName();

private final TvCastingApp tvCastingApp;
private final DiscoveredNodeData selectedCommissioner;

private boolean verifyOrEstablishConnectionSuccess;
private boolean openCommissioningWindowSuccess;
private boolean sendUdcSuccess;

public ConnectionFragment(TvCastingApp tvCastingApp, DiscoveredNodeData selectedCommissioner) {
this.tvCastingApp = tvCastingApp;
this.selectedCommissioner = selectedCommissioner;
}

/**
* Use this factory method to create a new instance of this fragment using the provided
* parameters.
*
* @return A new instance of fragment CommissioningFragment.
*/
public static ConnectionFragment newInstance(
TvCastingApp tvCastingApp, DiscoveredNodeData selectedCommissioner) {
return new ConnectionFragment(tvCastingApp, selectedCommissioner);
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Callback callback = (ConnectionFragment.Callback) this.getActivity();

SuccessCallback<VideoPlayer> onConnectionSuccess =
new SuccessCallback<VideoPlayer>() {
@Override
public void handle(VideoPlayer videoPlayer) {
Log.d(TAG, "handle() called on OnConnectionSuccess with " + videoPlayer);
callback.handleCommissioningComplete();
}
};

FailureCallback onConnectionFailure =
new FailureCallback() {
@Override
public void handle(MatterError matterError) {
Log.d(TAG, "handle() called on OnConnectionFailure with " + matterError);
}
};

SuccessCallback<ContentApp> onNewOrUpdatedEndpoints =
new SuccessCallback<ContentApp>() {
@Override
public void handle(ContentApp contentApp) {
Log.d(TAG, "handle() called on OnNewOrUpdatedEndpoint with " + contentApp);
}
};

if (selectedCommissioner != null && selectedCommissioner.isPreCommissioned()) {
VideoPlayer videoPlayer = selectedCommissioner.toConnectableVideoPlayer();
Log.d(TAG, "Calling verifyOrEstablishConnectionSuccess with VideoPlayer: " + videoPlayer);
this.verifyOrEstablishConnectionSuccess =
tvCastingApp.verifyOrEstablishConnection(
videoPlayer, onConnectionSuccess, onConnectionFailure, onNewOrUpdatedEndpoints);
} else {
Log.d(TAG, "Running commissioning");
this.openCommissioningWindowSuccess =
tvCastingApp.openBasicCommissioningWindow(
GlobalCastingConstants.CommissioningWindowDurationSecs,
new MatterCallbackHandler() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on CommissioningComplete event with " + error);
}
},
onConnectionSuccess,
onConnectionFailure,
onNewOrUpdatedEndpoints);

if (this.openCommissioningWindowSuccess) {
if (selectedCommissioner != null && selectedCommissioner.getNumIPs() > 0) {
String ipAddress = selectedCommissioner.getIpAddresses().get(0).getHostAddress();
Log.d(
TAG,
"ConnectionFragment calling tvCastingApp.sendUserDirectedCommissioningRequest with IP: "
+ ipAddress
+ " port: "
+ selectedCommissioner.getPort());

this.sendUdcSuccess = tvCastingApp.sendCommissioningRequest(selectedCommissioner);
}
}
}

return inflater.inflate(R.layout.fragment_connection, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String commissioningWindowStatus = "";
if (selectedCommissioner != null && selectedCommissioner.isPreCommissioned()) {
commissioningWindowStatus = "Establishing connection with selected Video Player";
} else {
commissioningWindowStatus = "Failed to open commissioning window";
if (this.openCommissioningWindowSuccess) {
commissioningWindowStatus = "Commissioning window has been opened. Commission manually.";
if (this.sendUdcSuccess) {
commissioningWindowStatus =
"Commissioning window has been opened. Commissioning requested from "
+ selectedCommissioner.getDeviceName();
}
TextView onboardingPayloadView = getView().findViewById(R.id.onboardingPayload);
onboardingPayloadView.setText(
"Onboarding PIN: "
+ GlobalCastingConstants.SetupPasscode
+ "\nDiscriminator: "
+ GlobalCastingConstants.Discriminator);
}
}

TextView commissioningWindowStatusView = getView().findViewById(R.id.commissioningWindowStatus);
commissioningWindowStatusView.setText(commissioningWindowStatus);
}

/** Interface for notifying the host. */
public interface Callback {
/** Notifies listener to trigger transition on completion of commissioning */
void handleCommissioningComplete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
import chip.platform.NsdManagerServiceResolver;
import chip.platform.PreferencesConfigurationManager;
import chip.platform.PreferencesKeyValueStoreManager;
import com.chip.casting.AppParameters;
import com.chip.casting.DACProviderStub;
import com.chip.casting.DiscoveredNodeData;
import com.chip.casting.TvCastingApp;
import com.chip.casting.util.GlobalCastingConstants;
import java.util.Random;

public class MainActivity extends AppCompatActivity
implements CommissionerDiscoveryFragment.Callback,
CommissioningFragment.Callback,
ConnectionFragment.Callback,
SelectClusterFragment.Callback {

private static final String TAG = MainActivity.class.getSimpleName();
Expand All @@ -46,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) {

@Override
public void handleCommissioningButtonClicked(DiscoveredNodeData commissioner) {
showFragment(CommissioningFragment.newInstance(tvCastingApp, commissioner));
showFragment(ConnectionFragment.newInstance(tvCastingApp, commissioner));
}

@Override
Expand Down Expand Up @@ -90,7 +92,12 @@ private void initJni() {
chipAppServer = new ChipAppServer();
chipAppServer.startApp();

tvCastingApp.init();
AppParameters appParameters = new AppParameters();
byte[] rotatingDeviceIdUniqueId =
new byte[AppParameters.MIN_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH];
new Random().nextBytes(rotatingDeviceIdUniqueId);
appParameters.setRotatingDeviceIdUniqueId(rotatingDeviceIdUniqueId);
tvCastingApp.init(appParameters);
}

private void showFragment(Fragment fragment, boolean showOnBack) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.chip.casting;

public class AppParameters {
public static final int MIN_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH = 16;

private byte[] rotatingDeviceIdUniqueId;

public void setRotatingDeviceIdUniqueId(byte[] rotatingDeviceIdUniqueId) {
this.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueId;
}

public byte[] getRotatingDeviceIdUniqueId() {
return rotatingDeviceIdUniqueId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class DiscoveredNodeData {
private int numIPs;
private List<InetAddress> ipAddresses;

private VideoPlayer connectableVideoPlayer;

public DiscoveredNodeData(NsdServiceInfo serviceInfo) {
Map<String, byte[]> attributes = serviceInfo.getAttributes();
this.deviceName = new String(attributes.get(KEY_DEVICE_NAME), StandardCharsets.UTF_8);
Expand All @@ -69,6 +71,18 @@ public DiscoveredNodeData(NsdServiceInfo serviceInfo) {
this.numIPs = 1;
}

void setConnectableVideoPlayer(VideoPlayer videoPlayer) {
this.connectableVideoPlayer = videoPlayer;
}

public boolean isPreCommissioned() {
return connectableVideoPlayer != null;
}

public VideoPlayer toConnectableVideoPlayer() {
return connectableVideoPlayer;
}

public String getHostName() {
return hostName;
}
Expand Down
Loading

0 comments on commit d0a3d57

Please sign in to comment.