610 likes | 771 Views
Communicating with Devices. Prasun Dewan. Department of Computer Science University of North Carolina dewan@unc.edu. Steps to UPnP Networking. 3 Control. 4 Eventing. 5 Presentation. 0 Control point and device get addresses 1 Control point finds interesting device
E N D
Communicating with Devices Prasun Dewan Department of Computer Science University of North Carolina dewan@unc.edu
Steps to UPnP Networking 3 Control 4 Eventing 5 Presentation 0 Control point and device get addresses 1 Control point finds interesting device 2* Control point learns about device capabilities 3 Control point invokes actions on device 4 Control point listens to state changes of device 5 Control point controls device and/or views device status using HTML UI 2* Description 1 Discovery 0 Addressing
Example Service <?xml version="1.0" ?> <scpd xmlns="urn:schemas-upnp-org:service-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion>
Example Action List <actionList> <action> <name>PowerOn</name> </action> <action> <name>SetChannel</name> <argumentList> <argument> <name>Channel</name> <relatedStateVariable>Channel</relatedStateVariable> <direction>in</direction> </argument> </argumentList> </action> …. <actionList>
Example Variables <serviceStateTable> <stateVariable sendEvents="yes"> <name>Power</name> <dataType>Boolean</dataType> <defaultValue>0</defaultValue> </stateVariable> <stateVariable sendEvents="yes"> <name>Channel</name> <dataType>i4</dataType> <allowedValueRange> <minimum>1</minimum> <maximum>100</maximum> <step>1</step> </allowedValueRange> <defaultValue>1</defaultValue> </stateVariable> ….. </serviceStateTable>
Example Server Code • Object processMessages (Message message) { • switch (message.kind) • case GET_VAR_REQUEST: • switch ((GetVarMessage) message).varName) • case “Channel”: message.result = getChannel(); • … • case ACTION_REQUEST: • actionMessage = (ActionMessage) message. • switch (actionMessage.actionName) • case “setChannel”: setChannel(parseString(actionMessage.params[0])) • … • } • int channel; • int getChannel () { return curentChannel}; • void setChannel (int newChannel) { • channel = newChannel; • UPnP.announce(“Channel”, toString(getChannel()); • } • ...
High Programming Cost • Device developer must: • define the XML-based external representation of the device • translate the client operation-invocation and variable-access requests to local operation-invocations • announce variable change notifications • Exporting functionality requires more code than implementing it in example Intel device • not counting UI code • Cost proportional to complexity of type. • Reason for not allowing complex types?
High Maintenance Cost • Information repeated multiple times • operation implementation code • action list • state variable table • message processing code • event announcement code • All repetitions must be changed • tedious • error-prone • Channel -> Current Channel requires 9 changes!
Changed Action List <actionList> <action> <name>PowerOn</name> </action> <action> <name>SetCurrentChannel</name> <argumentList> <argument> <name>CurrentChannel</name> <relatedStateVariable>CurrentChannel</relatedStateVariable> <direction>in</direction> </argument> </argumentList> </action> …. <actionList>
Changed State Variable Table <serviceStateTable> <stateVariable sendEvents="yes"> <name>Power</name> <dataType>Boolean</dataType> <defaultValue>0</defaultValue> </stateVariable> <stateVariable sendEvents="yes"> <name>CurrentChannel</name> <dataType>i4</dataType> <allowedValueRange> <minimum>1</minimum> <maximum>100</maximum> <step>1</step> </allowedValueRange> <defaultValue>1</defaultValue> </stateVariable> ….. </serviceStateTable>
Changed Server Code • Object processMessages (Message message) { • switch (message.kind) • case GET_VAR_REQUEST: • switch ((GetVarMessage) message).varName) • case “CurrentChannel”: message.result = getCurrentChannel(); • … • case ACTION_REQUEST: • actionMessage = (ActionMessage) message. • switch (actionMessage.actionName) • case “setCurrentChannel”: setCurrentChannel(parseString(actionMessage.params[0])) • … • } • int channel; • int getCurrentChannel () {return channel}; • void setCurrentChannel (int newChannel) { • channel = newChannel; • UPnP.announce(“CurrentChannel”, toString(getCurrentChannel()); • } • ...
Ideal Developer Effort int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } ...
No Programmer-Defined Types • XML defines 24 data types • ui1, ui2, ui4, i1, i2, i4, int • r4, r8, number, fixed.14.4, float • char, string • date, dateTime, dateTime.tz, time, time.tz • boolean • bin.base64, bin.hex • uri • uuid
Dynamic programmer-defined collection No Programmer-Defined Types • Only supports predefined types • state variables • action parameters • No way to model dynamic composites
Generating Action List External Description Device Code Actions Generator
Mainly syntactic issue Static approach precompiler Dynamic approach reflection vcr.getClass().getMethods() method.getName() method.getParameterTypes() Done in ICrafter (Stanford) How to get related state variable? Generating Action Descriptions int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } <action list> <action> <name>SetCurrentChannel</name> <argumentList> <argument> <name>NewChannel</name> <relatedStateVariable> CurrentChannel </relatedStateVariable> <direction>in</direction> </argument> </argumentList> </action> …. </actionList>
Why variables? • Clients may view device as state manager • Because their user has this view. • VCR user interface • May compose state • aggregating sensors • More abstract to associate events with variable changes rather than method invocations • Channel changed vs.SetChannel called • Similarly access and concurrency control state specific
Generating External Representation External Description Actions Device class Generator Variables • Problem in general unsolvable • Need help from programmer
Basic idea Object state stored in internal vars. Make them public. Drawbacks Violates encapsulation Changing internal representation changes clients Not all state may be stored How to get Related state vars Min, max range How to generate events public var could be changed directly Generating Variable Descriptions public int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } … <serviceStateTable> <stateVariable sendEvents="yes"> <name>Channel</name> <dataType>i4</dataType> <allowedValueRange> <minimum>1</minimum> <maximum>100</maximum> <step>1</step> </allowedValueRange> <defaultValue>1</defaultValue> </stateVariable> ….. </serviceStateTable>
Abstract data type helps by exposing logical structure using standard system-defined interface (TreeNode) Approach used in Swing table widget Equivalent to writing external description extra programming effort extra maintenance effort no type checking (everything TreeNode) Cannot generate types of variables must use common interfaces and associated object files Interface-based extraction public class VCR implements TreeNode{ int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } … } publicVector getVarNames(); publicTreeNodegetVar(StringfieldName); public void setVar(String fieldName, val TreeNode)
Can use relationships between operation names and signatures to derive external variables (properties) channel : int related state variable setChannel changes channel Relationships defined by Java beans Pattern-based Approach int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } …
Simple Properties in Java • Defined by a pair of ‘getter’/’setter’ methods: String getTitle(); void setTitle(String newTitle) define a title property of type String. • In general, <PropertyType> get<PropertyName>() void set<PropertyName>(<PropertyType>) define a simple property named <PropertyName> of type <PropertyType> with read/write semantics.
Role of JavaBeans Properties • ‘Properties are discrete named attributes of a Java Bean that can affect its appearance, or its behavior.’ • typical properties: • font • color • size
Properties as Record Fields int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } … Main idea: • consider properties as elements of the logical structure of the object. • record fields Problems • Forces conventions • Channel() instead of getChannel()? • Legacy code • Min, max range? <serviceStateTable> <stateVariable sendEvents="yes"> <name>Channel</name> <dataType>i4</dataType> <allowedValueRange> <minimum>1</minimum> <maximum>100</maximum> <step>1</step> </allowedValueRange> <defaultValue>1</defaultValue> </stateVariable> ….. </serviceStateTable>
Property Specification • Approach: • separate property specification and interpretation • Mechanism • introduce a pattern language for property specification
User-defined, but less work and no duplication Implementation must conform to specified pattern Pattern specifications Pattern specification Property Extractor Property Definitions Device Operations • Approach: • separate property specification and interpretation • Mechanism • introduce a pattern language for property specification
Examples Literals Free Variables Unified • Specification 1 String getTitle(); void setTitle(String newTitle) define a title property of type String. • Specification 2 Stringtitle(); void setTitle(String newTitle) define a title property of type String. • Grammar? • Methods as sentences • Property name and types not known • Must be extracted • Unification • Methods as facts • Property names and types as unified variables
Property Specification Language • Canonical representation of method signatures: <return_type> method_name(arg1_type, …,argN_type) • An example specification: simple properties 1. Method pattern specifications: getter = <.GetType.> get.PropName.() setter = <void> set.PropName.(.SetType.) • pattern variables: GetType, PropName, SetType • example matches: getter:String getTitle() {GetType == “String”,PropName == “Title”} setter:void setTitle(String) {SetType == “String”, PropName == “Title”}
Java Bean Specification with Constraints property type = simple access methods = getter, setter getter = <.GetType.> get.PropName.() setter = <void> set.PropName.(.SetType.) constraints getter.PropName == setter.PropName getter.GetType == setter.SetType name = getter.PropName end
Examples • Specification 1 String getTitle(); void setTitle(String newTitle) define a title property of type String. • Specification 2 Stringtitle(); void setTitle(String newTitle) define a title property of type String.
Alternative Bean Specification property type = simple access methods = getter, setter getter = <.GetType.>.PropName.() setter = <void> set.PropName.(.SetType.) constraints getter.PropName == setter.PropName getter.GetType == setter.SetType name = getter.PropName end
Properties as Record Fields int channel; int getChannel () { return channel}; void setChannel (int newChannel) { channel = newChannel; } … • Allows • Channel() instead of getChannel() • Legacy code • Issues • Min, max range? <serviceStateTable> <stateVariable sendEvents="yes"> <name>Channel</name> <dataType>i4</dataType> <allowedValueRange> <minimum>1</minimum> <maximum>100</maximum> <step>1</step> </allowedValueRange> <defaultValue>1</defaultValue> </stateVariable> ….. </serviceStateTable>
Min, Max Extensions Additional Constraints Property type = simple access methods = min, max min = <int> getMin.PropName.() max = <int> getMax.PropName.() step = <int> getStep.PropName.() … constraints getter.PropName==min.PropName== max.PropName end
Alternative Min, Max Extensions Constraints on variable declarations property type = simple access fields = min, max, step min = <final> <int> MIN_.PropName. max = <final> <int> MAX_.PropName. step = <final> <int> STEP_.PropName. constraints min.PropName==max.PropName== step.PropName == getter.PropName end
Dynamic programmer-defined collection No Programmer-Defined Types • Only supports predefined types • state variables • action parameters • No way to model dynamic composites
Two issues • Representation of programmer-defined types in XML • Seems to be syntactic issue • Generating external representation • Static (Record) structures addressed • JavaBeans defines field properties • Language allows convention definitions • Dynamic structures?
Indexed Properties in Java • An indexed property is a simple property of an array type: Section[] getSection() void setSection( Section[] section) with two additional methods: Section getSection( int index) void setSection( Section s, int index) • Emulates array semantics in procedural languages
Understand Java Vector • Cannot support programmer-defined dynamic list class VCR { void power(); … int getCurrentChannel() ; void setCurrentChannel(int newVal) ; Vector getSettings(); void setSettings(Vector newVal) }
Example Programmer-defined List class VCR { void power(); … int getCurrentChannel() ; void setCurrentChannel(int newVal) ; int size(); Setting elementAt(int index); void removeElement(Setting newVal); void addElement (Setting newVal); void setElementAt(Setting newVal, int index); }
Sequence properties insert = <void> insert.Prop.at( int, .InsType.) remove = <void> remove.Prop.at( int) lookup = <.GetType.> .Prop.At( int) set = <void> set.Prop.At( int, .SetType.) count = <int> size() property type = sequence accessmethods = insert, remove, lookup, count, set constraints insert.Prop == remove.Prop == lookup.Prop insert.InsType == lookup.SetType == lookup.GetType name = insert.Prop element type = insert.InsType publicint size(); publicint settingAt(int index); publicvoid setSettingAt(int index, Setting newVal); publicvoid insertSettingAt(int index, Setting newVal);
Programmer-Defined Types in External Representation • Concrete Constructors • Pascal enumeration • Subrange • Hashtable • Array • Sequence (variable size list) • Record • Not abstract types • Appliance object is abstract type • Must deconstruct object so that variables are known, that is, must map it to concrete type
Pattern specifications Pattern specification Property Extractor Property Definitions Device Operations Programmer must conform to specified pattern
Conforming to Patterns • Makes code understandable to humans • Also makes code understandable to system tools • Bean builder • Property Extractor • Unlike Bean framework, the patterns chosen by users • System adapts to application interfaces rather than vice versa • More flexible than the alternative of system-defined interfaces • Pattern specification without pattern variables is simply an interface
Sequence interface insert = <void> insertElementat( int, Object) remove = <void> removeElementAt( int) lookup = Object elementAt( int) set = <void> setElementAt( int, Object) count = <int> size() property type = sequence accessmethods = insert, remove, lookup, count, set name = vector element type = Object • Fixes method names • Fixes element type to Object • not Setting • no type checking publicint size(); publicint elementAt(int index); publicvoid setElementAt(int index, Object newVal); publicvoid insertElementAt(int index, Object newVal); publicvoid insertElementAt(int index, Object newVal);
Pattern Variables Allowing Multiple Methods Names/Element Types insert = <void> insert.Prop.at( int, .InsType.) remove = <void> remove.Prop.at( int) lookup = <.GetType.> .Prop.At( int) set = <void> set.Prop.At( int, .SetType.) count = <int> size() property type = sequence accessmethods = insert, remove, lookup, count, set constraints insert.Prop == remove.Prop == lookup.Prop insert.InsType == remove.SetType == lookup.GetType name = insert.Prop element type = insert.InsType publicint size(); publicint elementAt(int index); publicvoid setElementAt(int index, Object newVal); publicvoid insertElementAt(int index, Object newVal); public void removeElementAt(int index, Object newVal) publicint size(); publicint settingAt(int index); publicvoid setSettingAt(int index, Setting newVal); publicvoid insertSettingAt(int index, Setting newVal); publicvoid removeElementAt(int index);
Alternative Sequence properties with same access methods insert = <void> insert.Prop.at( int, .InsType.) remove = <void> remove.Prop.at( int) index = <.GetType.> .Prop.At( int) set = <void> set.Prop.At( int, .SetType.) count = <int> count() property type = sequence accessmethods = insert, remove, index, count, set constraints insert.Prop == remove.Prop == index.Prop insert.InsType == remove.SetType == lookup.GetType name = insert.Prop element type = insert.InsType publicint count(); publicint settingAt(int index); publicvoid setSettingAt(int index, Setting newVal); publicvoid insertSettingAt(int index, Setting newVal); publicvoid removeElementAt(int index);
Alternative Sequence properties with different access methods insert = <void> insert.Prop.at( int, .InsType.) remove = <void> remove.Prop.at( int) iterate = Enumeration elements() set = <void> set.Prop.At( int, .SetType.) property type = sequence accessmethods = insert, remove, iterate, set constraints insert.Prop == remove.Prop == lookup.Prop insert.InsType == remove.SetType == lookup.GetType name = insert.Prop element type = insert.InsType public Enumeration elements(); publicvoid setSettingAt(int index, Setting newVal); publicvoid insertSettingAt(int index, Setting newVal); publicvoid removeElementAt(int index);
Reducing High Programming Cost • Device developer must: • define the XML-based external representation of the device • system does it automatically, mapping operations to external representation • translate the client operation-invocation and variable-access requests to local operation-invocations • based on its knowledge of the mapping it can translate automatically • announce variable change notifications • system does successive object diffs to announce events automatically
Subscription Manager Separate from device Allows clients to register interests in device Forwards announcements to them Differ assumes subscription manager exists Takes successive snapshots When? How? Generating Events Device Object Differ Subscription Manager register interest forward event Client
More maintainable When Snapshots Taken? • Client requests • user refreshed • wants the differences rather than complete values • Some client has taken an action on device • informs some global object about it • other clients can now be notified • Timer-based • differ polls • when upto date information not crucial • Device requests • Differ.announce() vs. • UPnP.announce(“Channel”, toString(getChannel());