@@ -773,7 +773,8 @@ func connect(selectedCastingPlayer: MCCastingPlayer?) {
773
773
774
774
### Select an Endpoint on the Casting Player
775
775
776
- _{Complete Endpoint selection examples: [Linux](linux/simple-app-helper.cpp)}_
776
+ _{Complete Endpoint selection examples: [Linux](linux/simple-app-helper.cpp) |
777
+ [iOS](darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift)}_
777
778
778
779
On a successful connection with a `CastingPlayer`, a Casting Client may select
779
780
one of the Endpoints to interact with based on its attributes (e.g. Vendor ID,
@@ -799,6 +800,19 @@ if (it != endpoints.end())
799
800
}
800
801
```
801
802
803
+ On iOS, it can select an `MCEndpoint` similarly and as shown below.
804
+
805
+ ```swift
806
+ // VendorId of the MCEndpoint on the MCCastingPlayer that the MCCastingApp desires to interact with after connection
807
+ let sampleEndpointVid: Int = 65521
808
+ ...
809
+ // select the MCEndpoint on the MCCastingPlayer to invoke the command on
810
+ if let endpoint: MCEndpoint = castingPlayer.endpoints().filter({ $0.vendorId().intValue == sampleEndpointVid}).first
811
+ {
812
+ ...
813
+ }
814
+ ```
815
+
802
816
## Interacting with a Casting Endpoint
803
817
804
818
Once the Casting Client has selected an `Endpoint`, it is ready to
@@ -819,13 +833,14 @@ response types to use with these APIs:
819
833
820
834
### Issuing Commands
821
835
822
- _{Complete Command invocation examples: [Linux](linux/simple-app-helper.cpp)}_
836
+ _{Complete Command invocation examples: [Linux](linux/simple-app-helper.cpp) |
837
+ [iOS](darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift)}_
823
838
824
- The Casting Client can get a reference to a `endpoint ` on a `CastingPlayer`,
839
+ The Casting Client can get a reference to an `Endpoint ` on a `CastingPlayer`,
825
840
check if it supports the required cluster/command, and send commands to it. It
826
841
can then handle any command response / error the `CastingPlayer` sends back.
827
842
828
- On Linux, for example, given an `endpoint `, it can send a `LaunchURL` command
843
+ On Linux, for example, given an `Endpoint `, it can send a `LaunchURL` command
829
844
(part of the Content Launcher cluster) by calling the `Invoke` API on a
830
845
`Command` of type
831
846
`matter::casting::core::Command<chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type>`
@@ -865,9 +880,65 @@ void InvokeContentLauncherLaunchURL(matter::casting::memory::Strong<matter::cast
865
880
}
866
881
```
867
882
883
+ On iOS, given an `MCEndpoint` endpoint, it can send a `LaunchURL` command (part
884
+ of the Content Launcher cluster) by calling the `invoke` API on a
885
+ `MCContentLauncherClusterLaunchURLCommand`
886
+
887
+ ```swift
888
+ // validate that the selected endpoint supports the ContentLauncher cluster
889
+ if(!endpoint.hasCluster(MCEndpointClusterTypeContentLauncher))
890
+ {
891
+ self.Log.error("No ContentLauncher cluster supporting endpoint found")
892
+ DispatchQueue.main.async
893
+ {
894
+ self.status = "No ContentLauncher cluster supporting endpoint found"
895
+ }
896
+ return
897
+ }
898
+
899
+ // get ContentLauncher cluster from the endpoint
900
+ let contentLaunchercluster: MCContentLauncherCluster = endpoint.cluster(for: MCEndpointClusterTypeContentLauncher) as! MCContentLauncherCluster
901
+
902
+ // get the launchURLCommand from the contentLauncherCluster
903
+ let launchURLCommand: MCContentLauncherClusterLaunchURLCommand? = contentLaunchercluster.launchURLCommand()
904
+ if(launchURLCommand == nil)
905
+ {
906
+ self.Log.error("LaunchURL not supported on cluster")
907
+ DispatchQueue.main.async
908
+ {
909
+ self.status = "LaunchURL not supported on cluster"
910
+ }
911
+ return
912
+ }
913
+
914
+ // create the LaunchURL request
915
+ let request: MCContentLauncherClusterLaunchURLRequest = MCContentLauncherClusterLaunchURLRequest()
916
+ request.contentURL = contentUrl
917
+ request.displayString = displayString
918
+
919
+ // call invoke on launchURLCommand while passing in a completion block
920
+ launchURLCommand!.invoke(request, context: nil, completion: { context, err, response in
921
+ DispatchQueue.main.async
922
+ {
923
+ if(err == nil)
924
+ {
925
+ self.Log.info("LaunchURLCommand invoke completion success with \( String(describing: response))")
926
+ self.status = "Success. Response data: \( String(describing: response?.data))"
927
+ }
928
+ else
929
+ {
930
+ self.Log.error("LaunchURLCommand invoke completion failure with \( String(describing: err))")
931
+ self.status = "Failure: \( String(describing: err))"
932
+ }
933
+ }
934
+ },
935
+ timedInvokeTimeoutMs: 5000) // time out after 5000ms
936
+ ```
937
+
868
938
### Read Operations
869
939
870
- _{Complete Attribute Read examples: [Linux](linux/simple-app-helper.cpp)}_
940
+ _{Complete Attribute Read examples: [Linux](linux/simple-app-helper.cpp) |
941
+ [iOS](darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift)}_
871
942
872
943
The `CastingClient` may read an Attribute from the `Endpoint` on the
873
944
`CastingPlayer`. It should ensure that the desired cluster / attribute are
@@ -914,11 +985,69 @@ void ReadApplicationBasicVendorID(matter::casting::memory::Strong<matter::castin
914
985
}
915
986
```
916
987
988
+ On iOS, given a `MCEndpoint`, the `VendorID` can be read similarly, by calling
989
+ the `read` API on the `MCApplicationBasicClusterVendorIDAttribute`
990
+
991
+ ```swift
992
+ // validate that the selected endpoint supports the ApplicationBasic cluster
993
+ if(!endpoint.hasCluster(MCEndpointClusterTypeApplicationBasic))
994
+ {
995
+ self.Log.error("No ApplicationBasic cluster supporting endpoint found")
996
+ DispatchQueue.main.async
997
+ {
998
+ self.status = "No ApplicationBasic cluster supporting endpoint found"
999
+ }
1000
+ return
1001
+ }
1002
+
1003
+ // get ApplicationBasic cluster from the endpoint
1004
+ let applicationBasiccluster: MCApplicationBasicCluster = endpoint.cluster(for: MCEndpointClusterTypeApplicationBasic) as! MCApplicationBasicCluster
1005
+
1006
+ // get the vendorIDAttribute from the applicationBasiccluster
1007
+ let vendorIDAttribute: MCApplicationBasicClusterVendorIDAttribute? = applicationBasiccluster.vendorIDAttribute()
1008
+ if(vendorIDAttribute == nil)
1009
+ {
1010
+ self.Log.error("VendorID attribute not supported on cluster")
1011
+ DispatchQueue.main.async
1012
+ {
1013
+ self.status = "VendorID attribute not supported on cluster"
1014
+ }
1015
+ return
1016
+ }
1017
+
1018
+ // call read on vendorIDAttribute and pass in a completion block
1019
+ vendorIDAttribute!.read(nil) { context, before, after, err in
1020
+ DispatchQueue.main.async
1021
+ {
1022
+ if(err != nil)
1023
+ {
1024
+ self.Log.error("Error when reading VendorID value \( String(describing: err))")
1025
+ self.status = "Error when reading VendorID value \( String(describing: err))"
1026
+ return
1027
+ }
1028
+
1029
+ if(before != nil)
1030
+ {
1031
+ self.Log.info("Read VendorID value: \( String(describing: after)) Before: \( String(describing: before))")
1032
+ self.status = "Read VendorID value: \( String(describing: after)) Before: \( String(describing: before))"
1033
+ }
1034
+ else
1035
+ {
1036
+ self.Log.info("Read VendorID value: \( String(describing: after))")
1037
+ self.status = "Read VendorID value: \( String(describing: after))"
1038
+ }
1039
+ }
1040
+ }
1041
+ ```
1042
+
917
1043
### Subscriptions
918
1044
919
1045
_{Complete Attribute subscription examples:
920
1046
[Linux](linux/simple-app-helper.cpp)}_
921
1047
1048
+ _{Complete Attribute Read examples: [Linux](linux/simple-app-helper.cpp) |
1049
+ [iOS](darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift)}_
1050
+
922
1051
A Casting Client may subscribe to an attribute on an `Endpoint` of the
923
1052
`CastingPlayer` to get data reports when the attributes change.
924
1053
@@ -966,7 +1095,69 @@ void SubscribeToMediaPlaybackCurrentState(matter::casting::memory::Strong<matter
966
1095
}
967
1096
```
968
1097
1098
+ On iOS, given a `MCEndpoint`, `CurrentState` can be subscribed to by calling the
1099
+ `subscribe` API on the it can subscribe to the `CurrentState` (part of the Media
1100
+ Playback Basic cluster) by calling the `Subscribe` API on the
1101
+ `MCMediaPlaybackClusterCurrentStateAttribute`
1102
+
1103
+ ```swift
1104
+ // validate that the selected endpoint supports the MediaPlayback cluster
1105
+ if(!endpoint.hasCluster(MCEndpointClusterTypeMediaPlayback))
1106
+ {
1107
+ self.Log.error("No MediaPlayback cluster supporting endpoint found")
1108
+ DispatchQueue.main.async
1109
+ {
1110
+ self.status = "No MediaPlayback cluster supporting endpoint found"
1111
+ }
1112
+ return
1113
+ }
1114
+
1115
+ // get MediaPlayback cluster from the endpoint
1116
+ let mediaPlaybackCluster: MCMediaPlaybackCluster = endpoint.cluster(for: MCEndpointClusterTypeMediaPlayback) as! MCMediaPlaybackCluster
1117
+
1118
+ // get the currentStateAttribute from the mediaPlaybackCluster
1119
+ let currentStateAttribute: MCMediaPlaybackClusterCurrentStateAttribute? = mediaPlaybackCluster.currentStateAttribute()
1120
+ if(currentStateAttribute == nil)
1121
+ {
1122
+ self.Log.error("CurrentState attribute not supported on cluster")
1123
+ DispatchQueue.main.async
1124
+ {
1125
+ self.status = "CurrentState attribute not supported on cluster"
1126
+ }
1127
+ return
1128
+ }
1129
+
1130
+ // call read on currentStateAttribute and pass in a completion block
1131
+ currentStateAttribute!.read(nil) { context, before, after, err in
1132
+
1133
+ let dateFormatter = DateFormatter()
1134
+ dateFormatter.dateFormat = "HH:mm:ss"
1135
+ let currentTime = dateFormatter.string(from: Date())
1136
+ DispatchQueue.main.async
1137
+ {
1138
+ if(err != nil)
1139
+ {
1140
+ self.Log.error("Error when reading CurrentState value \( String(describing: err)) at \( currentTime)")
1141
+ self.status = "Error when reading CurrentState value \( String(describing: err)) at \( currentTime)"
1142
+ return
1143
+ }
1144
+ if(before != nil)
1145
+ {
1146
+ self.Log.info("Read CurrentState value: \( String(describing: after)) Before: \( String(describing: before)) at \( currentTime)")
1147
+ self.status = "Read CurrentState value: \( String(describing: after)) Before: \( String(describing: before)) at \( currentTime)"
1148
+ }
1149
+ else
1150
+ {
1151
+ self.Log.info("Read CurrentState value: \( String(describing: after)) at \( currentTime)")
1152
+ self.status = "Read CurrentState value: \( String(describing: after)) at \( currentTime)"
1153
+ }
1154
+ }
1155
+ }
1156
+ ```
1157
+
969
1158
The Casting client can Shutdown all running Subscriptions by calling the
970
- `ShutdownAllSubscriptions` API on the `CastingApp`. See API and its
971
- documentation for [Linux](tv-casting-common/core/CastingApp.h), Android and
972
- [iOS](darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingApp.h).
1159
+ `ShutdownAllSubscriptions` API on the `CastingApp` on Linux/Android and
1160
+ `MCCastingApp` on iOS. See API and its documentation for
1161
+ [Linux](tv-casting-common/core/CastingApp.h),
1162
+ [Android](android/App/app/src/main/jni/com/matter/casting/core/CastingApp.java)
1163
+ and [iOS](darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingApp.h).
0 commit comments