Skip to content

Commit

Permalink
Completed Example 22-TLV8_Characteristics
Browse files Browse the repository at this point in the history
Must update Television.md documentation as well as Television Example to reflect recent changes to the Characteristics Apple made - there seems to be less flexibility in what needs to be defined to use the input sources.

Also need to add DisplayOrder Characteristic to TV documentation.
  • Loading branch information
HomeSpan committed Apr 23, 2024
1 parent a785c1f commit 3273f7f
Showing 1 changed file with 56 additions and 55 deletions.
111 changes: 56 additions & 55 deletions examples/22-TLV8_Characteristics/22-TLV8_Characteristics.ino
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
// Example 24: Demonstrates the use of the TLV8 Library //
// by implementing DisplayOrder, an optional //
// TLV8 Characteristic used with the TV Service //
// to sets the order in which TV Inputs are //
// to set the order in which TV Inputs are //
// displayed for selection in the Home App //
// //
////////////////////////////////////////////////////////////////
Expand All @@ -43,7 +43,7 @@
// NOTE: Please see the "Other Examples -> Television" sketch for complete details on how to implement a Television Service. The focus
// of this sketch is solely to demonstrate how to use the TLV8 Library to create TLV8 data for use with the DisplayOrder Characteristic.

// First we define a simple Television Input Source Service with only the Identifer and Name Characteristics
// First we define a simple Television Input Source Service

struct TVInput : Service::InputSource {

Expand All @@ -54,80 +54,81 @@ struct TVInput : Service::InputSource {

inputID = new Characteristic::Identifier(id);
inputName = new Characteristic::ConfiguredName(name);
new Characteristic::IsConfigured(1);
new Characteristic::IsConfigured(Characteristic::IsConfigured::CONFIGURED);
new Characteristic::CurrentVisibilityState(Characteristic::CurrentVisibilityState::VISIBLE);
}
};

// Next we define a very simple Television Service
// Next we define a simple Television Service

struct HomeSpanTV : Service::Television {

SpanCharacteristic *active = new Characteristic::Active(0,true); // TV ON/OFF (set to OFF at start-up)
SpanCharacteristic *activeID = new Characteristic::ActiveIdentifier(30,true); // Set TV to input source with ID=30
// SpanCharacteristic *displayOrder = new Characteristic::DisplayOrder(); // <-- This is the new TLV8 Characteristic. Note the constructor has no argument
SpanCharacteristic *active = new Characteristic::Active(0);
SpanCharacteristic *activeID = new Characteristic::ActiveIdentifier(10);

SpanCharacteristic *displayOrder = new Characteristic::DisplayOrder(); // <-- This is the new TLV8 Characteristic. Note the constructor has no argument

HomeSpanTV() : Service::Television() {
HomeSpanTV() : Service::Television() {

// Unlike the constructors for numerical and string-based Characteristics (such as ActiveIdentifier and ConfiguredName),
// we cannot set the initial value of TLV8 Characteristics during construction, but must instead first instantiate the
// Characteristic (as we did above), then build a TLV8 object with the information required by the TLV8 Characteristic, and
// then use setTLV() to load the completed TLV8 object into the Characteristic's value.
// Unlike the constructors for numerical and string-based Characteristics (such as ActiveIdentifier and ConfiguredName),
// we cannot set the initial value of TLV8 Characteristics during construction, but must instead first instantiate the
// Characteristic (as we did above), then build a TLV8 object with the information required by the TLV8 Characteristic, and
// then use setTLV() to load the completed TLV8 object into the Characteristic's value.

// The (undocumented by Apple!) TLV8 specifications for the DisplayOrder Characteristic are as follows:
// The (undocumented by Apple!) TLV8 specifications for the DisplayOrder Characteristic are as follows:

// TAG NAME FORMAT DESCRIPTION
// ---- ------------- ------ --------------------------------------------
// 0x01 inputSourceID uint32 ID of the Input Source to be displayed first
// 0x00 separator none Empty element to separate the inputSourceIDs
// 0x01 inputSourceID uint32 ID of the Input Source to be displayed second
// 0x00 separator none Empty element to separate the inputSourceIDs
// 0x01 inputSourceID uint32 ID of the Input Source to be displayed third
// 0x00 separator none Empty element to separate the inputSourceIDs
// etc...
// TAG NAME FORMAT DESCRIPTION
// ---- ------------- ------ --------------------------------------------
// 0x01 inputSourceID uint32 ID of the Input Source to be displayed first
// 0x00 separator none Empty element to separate the inputSourceIDs
// 0x01 inputSourceID uint32 ID of the Input Source to be displayed second
// 0x00 separator none Empty element to separate the inputSourceIDs
// 0x01 inputSourceID uint32 ID of the Input Source to be displayed third
// 0x00 separator none Empty element to separate the inputSourceIDs
// etc...

// To start, instantiate a new TLV8 object
TLV8 orderTLV; // creates an empty TLV8 object
// To start, instantiate a new TLV8 object

TLV8 orderTLV; // creates an empty TLV8 object

// Next, fill it with TAGS and VALUES based on the above specification. The easiest,
// though not necessarily most elegant, way to do this is as follows:
// Next, fill it with TAGS and VALUES based on the above specification. The easiest, though
// not necessarily most elegant, way to do this is by simply adding each TAG/VALUE as follows:

orderTLV.add(1,10); // TAG=1, VALUE=ID of first Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,20); // TAG=1, VALUE=ID of the second Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,50); // TAG=1, VALUE=ID of the third Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,30); // TAG=1, VALUE=ID of the fourth Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,40); // TAG=1, VALUE=ID of the fifth Input Source to be displayed
orderTLV.add(1,10); // TAG=1, VALUE=ID of first Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,20); // TAG=1, VALUE=ID of the second Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,50); // TAG=1, VALUE=ID of the third Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,30); // TAG=1, VALUE=ID of the fourth Input Source to be displayed
orderTLV.add(0); // TAG=0 (no value)
orderTLV.add(1,40); // TAG=1, VALUE=ID of the fifth Input Source to be displayed

// Based on the above structure, we expect the Home App to display our input sources based on their IDs
// in the following order: 100, 200, 500, 300, 400. These IDs must of course match the IDs you choose
// for your input sources when you create them at the end of this sketch in setup()
// Based on the above structure, we expect the Home App to display our input sources based on their IDs
// in the following order: 10, 20, 50, 30, 40. These IDs must of course match the IDs you choose
// for your input sources when you create them at the end of this sketch in setup()

// The final step is to load this TLV8 object into the DisplayOrder Characteristic
// The final step is to load this TLV8 object into the DisplayOrder Characteristic

// displayOrder->setTLV(orderTLV); // set the "value" of DisplayOrder to be the orderTLV object we just created
displayOrder->setTLV(orderTLV); // set the "value" of DisplayOrder to be the orderTLV object we just created

// That's it - you've created your first TLV8 Characteristic!
}
// That's it - you've created your first TLV8 Characteristic!
}

// Below we define the usual update() loop. There is nothing "TLV-specific" about this part of the code
boolean update() override {
// Below we define the usual update() loop. There is nothing "TLV-specific" about this part of the code

boolean update() override {

if(active->updated()){
Serial.printf("Set TV Power to: %s\n",active->getNewVal()?"ON":"OFF");
}
if(active->updated()){
LOG0("Set TV Power to: %s\n",active->getNewVal()?"ON":"OFF");
}

if(activeID->updated()){
Serial.printf("Set Input Source to ID=%d\n",activeID->getNewVal());
}
if(activeID->updated()){
LOG0("Set Input Source to ID=%d\n",activeID->getNewVal());
}

return(true);
}
return(true);
}
};

///////////////////////////////
Expand Down

0 comments on commit 3273f7f

Please sign in to comment.