Created initial Example 22 - TLV8_Characteristics
Requires some debugging...
This commit is contained in:
parent
4e5d03f63f
commit
3db4676b7d
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*********************************************************************************
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2024 Gregg E. Berman
|
||||||
|
*
|
||||||
|
* https://github.com/HomeSpan/HomeSpan
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// HomeSpan: A HomeKit implementation for the ESP32 //
|
||||||
|
// ------------------------------------------------ //
|
||||||
|
// //
|
||||||
|
// 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 //
|
||||||
|
// displayed for selection in the Home App //
|
||||||
|
// //
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "HomeSpan.h"
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
struct TVInput : Service::InputSource {
|
||||||
|
|
||||||
|
SpanCharacteristic *inputID;
|
||||||
|
SpanCharacteristic *inputName;
|
||||||
|
|
||||||
|
TVInput(uint32_t id, const char *name) : Service::InputSource() {
|
||||||
|
|
||||||
|
inputID = new Characteristic::Identifier(id);
|
||||||
|
inputName = new Characteristic::ConfiguredName(name);
|
||||||
|
new Characteristic::IsConfigured(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Next we define a very 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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
// 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...
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
|
||||||
|
if(active->updated()){
|
||||||
|
Serial.printf("Set TV Power to: %s\n",active->getNewVal()?"ON":"OFF");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(activeID->updated()){
|
||||||
|
Serial.printf("Set Input Source to ID=%d\n",activeID->getNewVal());
|
||||||
|
}
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
homeSpan.setLogLevel(2);
|
||||||
|
|
||||||
|
homeSpan.begin(Category::Television,"HomeSpan Television");
|
||||||
|
|
||||||
|
SPAN_ACCESSORY();
|
||||||
|
|
||||||
|
(new HomeSpanTV()) // Define a Television Service and link in the InputSources!
|
||||||
|
->addLink(new TVInput(10,"Xfinity"))
|
||||||
|
->addLink(new TVInput(20,"BlueRay Disc"))
|
||||||
|
->addLink(new TVInput(30,"Amazon Prime"))
|
||||||
|
->addLink(new TVInput(40,"Netflix"))
|
||||||
|
->addLink(new TVInput(50,"Hulu"))
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
homeSpan.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
@ -114,6 +114,7 @@ struct HapCharacteristics {
|
||||||
HAPCHAR( CurrentTemperature, 11, PR+EV, FLOAT, false );
|
HAPCHAR( CurrentTemperature, 11, PR+EV, FLOAT, false );
|
||||||
HAPCHAR( CurrentTiltAngle, C1, PR+EV, INT, false );
|
HAPCHAR( CurrentTiltAngle, C1, PR+EV, INT, false );
|
||||||
HAPCHAR( CurrentVisibilityState, 135, PR+EV, UINT8, true );
|
HAPCHAR( CurrentVisibilityState, 135, PR+EV, UINT8, true );
|
||||||
|
HAPCHAR( DisplayOrder, 136, PR+EV, TLV_ENC, true );
|
||||||
HAPCHAR( FilterLifeLevel, AB, PR+EV, FLOAT, false );
|
HAPCHAR( FilterLifeLevel, AB, PR+EV, FLOAT, false );
|
||||||
HAPCHAR( FilterChangeIndication, AC, PR+EV, UINT8, true );
|
HAPCHAR( FilterChangeIndication, AC, PR+EV, UINT8, true );
|
||||||
HAPCHAR( FirmwareRevision, 52, PR+EV, STRING, true );
|
HAPCHAR( FirmwareRevision, 52, PR+EV, STRING, true );
|
||||||
|
|
|
||||||
|
|
@ -429,6 +429,7 @@ namespace Service {
|
||||||
CREATE_SERV(Television,D8) // Defines a TV. Optional Linked Services: <b>InputSource</b> and <b>TelevisionSpeaker</b>.
|
CREATE_SERV(Television,D8) // Defines a TV. Optional Linked Services: <b>InputSource</b> and <b>TelevisionSpeaker</b>.
|
||||||
REQ(Active);
|
REQ(Active);
|
||||||
OPT(ActiveIdentifier);
|
OPT(ActiveIdentifier);
|
||||||
|
OPT(DisplayOrder);
|
||||||
OPT(RemoteKey);
|
OPT(RemoteKey);
|
||||||
OPT(PowerModeSelection);
|
OPT(PowerModeSelection);
|
||||||
OPT(ConfiguredName);
|
OPT(ConfiguredName);
|
||||||
|
|
@ -513,6 +514,7 @@ namespace Characteristic {
|
||||||
CREATE_CHAR(double,CurrentRelativeHumidity,0,0,100); // current humidity measured as a percentage
|
CREATE_CHAR(double,CurrentRelativeHumidity,0,0,100); // current humidity measured as a percentage
|
||||||
CREATE_CHAR(double,CurrentTemperature,0,0,100); // current temperature measured in Celsius
|
CREATE_CHAR(double,CurrentTemperature,0,0,100); // current temperature measured in Celsius
|
||||||
CREATE_CHAR(int,CurrentTiltAngle,0,-90,90); // current angle (in degrees) of slats from fully up or left (-90) to fully open (0) to fully down or right (90)
|
CREATE_CHAR(int,CurrentTiltAngle,0,-90,90); // current angle (in degrees) of slats from fully up or left (-90) to fully open (0) to fully down or right (90)
|
||||||
|
CREATE_CHAR(const char *,DisplayOrder,"",0,1); // specifies the order in which the TV inputs are displayed for selection in the Home App
|
||||||
CREATE_CHAR(double,FilterLifeLevel,100,0,100); // measured as a percentage of remaining life
|
CREATE_CHAR(double,FilterLifeLevel,100,0,100); // measured as a percentage of remaining life
|
||||||
CREATE_CHAR(uint8_t,FilterChangeIndication,0,0,1,NO_CHANGE_NEEDED,CHANGE_NEEDED); // indicates state of filter
|
CREATE_CHAR(uint8_t,FilterChangeIndication,0,0,1,NO_CHANGE_NEEDED,CHANGE_NEEDED); // indicates state of filter
|
||||||
CREATE_CHAR(const char *,FirmwareRevision,"1.0.0",0,1); // must be in form x[.y[.z]] - informational only
|
CREATE_CHAR(const char *,FirmwareRevision,"1.0.0",0,1); // must be in form x[.y[.z]] - informational only
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include "HomeSpan.h"
|
#include "HomeSpan.h"
|
||||||
|
|
||||||
CUSTOM_CHAR_TLV8(DisplayOrder,136,PR+EV);
|
|
||||||
CUSTOM_CHAR_DATA(TestData,333,PR+EV);
|
CUSTOM_CHAR_DATA(TestData,333,PR+EV);
|
||||||
|
|
||||||
struct HomeSpanTV : Service::Television {
|
struct HomeSpanTV : Service::Television {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue