Presentazione di PowerPoint

advertisement
Design and realization of
composable web services for home
automation
Elective in Software and Services
Mario Caruso
What we are going to see
• Brief introduction to home automation
systems.
• How to make home devices really
interoperable
• DPWS as a framework for dynamic web
services
• Implentation of a very simple web service for
controlling a lamp
• Practical demonstration
Smart Home [bus]
Devices’ heterogeneity
• Home automation system A + B
Making devices homogeneus
• Devices have to speak the same language.
• We must abstract a device from its specific
protocol.
• Each device has a software module (proxy)
able to communicate with it:
– Send commands
– Listen to sensed events
turnOff()
Protocol
independent
Light B
Proxy
Light interface
Light A Proxy
Protocol A
implementation
Light
actuator
(System A)
turnOn(
)
Protocol
dependent
B bus
A bus
Light A
Proxy
turnOn(
)
turnOff()
Light interface
Light B Proxy
Protocol B
implementation
Light
actuator
(System B)
SOA
• A proxy exposes device’s functionalities as Web
Services
• Web service pros:
– Autonomous
• The lifecycle of a proxy is independent from the others
• Self-contained functionalities
– Interoperable
• Abstracts the interface from the implementation (loosely coupled)
– Language and platform independent
– Remotely invocable
– Composable
Orchestrator
sensor
actuator
Orchestrator
Proxy 1
Proxy 2
Proxy 3
Proxies simply act as servers
Proxy 4
Proxy 5
Service implementation
• In the next slides we will see how to design
and implement services able to control home
automation devices.
• We will implement services by using the
DPWS stack. In particular we will use JMEDS
libraries.
– http://ws4d.e-technik.uni-rostock.de/jmeds/
What is DPWS
• DPWS = Devices Profile for Web Services
• a profile is a set of guidelines for how to use
Web Services technologies for a given purpose
or application.
• DPWS is a lightweight subset of WS
implementations particularly suited for
constrained resource devices.
DPWS Capabilities
•
•
•
•
Discover devices and their related services
Send/Receive messages to/from devices
Describe WS (through WSDL etc.)
Subscribe and receive events notifications
Rich service description as a contract
• When designing/developing a service we start
from its rich service description.
• The rich service description is composed by three
files:
– The variable type declaration
– The variable instance declaration
– The behaviour description
• In particular the developer must implement the
transition system that describes both the
conversational behaviour and the physical
behaviour.
Reminder
• How the conversational state differs from the
value of a variable?
– The conversational state gives an indication about
the actions that can be invoked on a service in a
specific moment (server-client interaction).
– The value of a variable reflects the “physical” state
of the device. i.e: the bulb is on or off
Conversational state example
Assuming that a lamp is modelled by this
transition system:
• If the lamp is in state A
• a client can invoke both turnOn
and turnOff operation
• But if the lamp is in state B
• a client can only invoke the turn
on operation
turnOn
turnOff
A
B
turnOn
A working example: DPWSLight
DPWSLight
service
Home automation bus
DPWSClient
(e.g. Orchestrator)
The behaviour model
<?xml version="1.0" encoding="UTF-8"?>
<service …
<ts>
<state name="B" type="initial-final">
<transition action="turnOn">
<target state="A" />
<postcondition variable="light">
<set-value value="0" />
</postcondition>
</transition>
</state>
<state name="A" type="initial-final">
<transition action="turnOff">
<target state="B" />
<postcondition variable="light">
<set-value value="0" />
</postcondition>
</transition>
</state>
</ts>
</service>
turnOff / light:=0
A
B
turnOn / ligth:=1
Creating states and variables
• Remember: states and variables can assume only
a finite set of values in order to make services’s
composition feasible.
• By looking at vdd/vml and sbl specifications files
we see that allowed states are {A,B} while
allowed values for light variable are {0,1}.
• Then we create two classes in charge of limiting
the possible values:
– one to represent the states
– and the other to represent the variable
Variables and states declaration
light_level.vml.xml
light-variable.vdd.xml
<?xml version="1.0" encoding="UTF-8"?>
<variable-model
...
name="LightLevel">
<?xml version="1.0"
encoding="UTF-8"?>
<home name="MyHome"
…
<variable name="light"
type="custom"
model="light_level.vml.xml" />
</home>
<value value="0" id="0"/>
<value value="1" id="1"/>
</variable-model>
<service …
<ts>
<state name="B" type="initial-final">
…
</state>
<state name="A" type="initial-final">
…
</state>
</ts>
</service>
light_type.sbl.xml
State Class
package common;
public class State {
public final static String STATE_A = "A";
public final static String STATE_B = "B";
private String state;
/**
* Create a State object and set its value to "off"
*/
public State(){
this.state = STATE_B;
}
public String getState(){
return state;
}
public void setStateA(){
this.state = STATE_A;
}
public void setStateB(){
this.state = STATE_B;
}
}
LightDevice class
• Then we create a class containing the “business
logic” of the lamp.
• Such class has:
– A state attribute, a light variable (and the related
accessor methods)
– a method for each action declared (turnOn and
turnOff) in the sbl.
• Note that this class is the only one aware of the
underlying specific home automation protocol. It
sends commands to the bus and listens for event
coming from the bus.
Implementing service behaviour
• Each method returns a boolean value
according to the sbl specification:
– If the current state of the lamp is “B”
• If on() method is invoked than we turn on the lamp and
return true
• If off() method is invoked than we return false, saying
to our client that is not possible to invoke such action in
the current conversational state
turnOff / light:=0
A
B
turnOn / ligth:=1
On method
/**
* Turns on the light
*/
public boolean on(){
boolean result = false;
if (state.getState().equals(State.STATE_B)){
/*
* Here the developer inserts protocol dependent
instructions
* to actuate the light.
*/
EDSbus.sendBMCOutputControl(deviceNumber,
sendingNumber, outputChannel, true);
result = true;
}
return result;
}
LightDevice class
LightDevice
•
•
•
•
boolean on()
boolean off()
String getState()
int getVariable()
Home automation bus
1..1
State
1..1 Variable
Adding web service capabilities to our lamp
• So far we developed a few classes able to
communicate with the bus, in particular the
LightDevice class.
1..1
State
LightDevice
1..1 Variable
• Now we will make it accessible through web
services.
Adding web service capabilities to our lamp
1..1
1..*
Device
1..1
1..*
Service
Operation
1..1
1..1
1..1
DPWSLight
LightService
1..1
OnOperation
OffOperation
GetStateOperation
1..1
1..1
1..1
GetValueOperation
State
1..1
LightDevice
1..1
Variable
GetSarOperation
DPWSLight class
public class DPWSLight extends DefaultDevice implements StateChangedListener
public DPWSLight(LightDevice light) {
super();
…
this.light = light;
service = new LightService();
OnOperation onOp = new OnOperation(light);
OffOperation offOp = new OffOperation(light);
GetStateOperation getStateOp = new GetStateOperation(light);
GetValueOperation getValueOp = new GetValueOperation(light);
GetServiceArchiveOperation getSarOp = new GetServiceArchiveOperation();
service.addOperation(onOp);
service.addOperation(offOp);
service.addOperation(getStateOp);
service.addOperation(getValueOp);
service.addOperation(getSarOp);
…
this.addService(service);
OnOperation
public class OnOperation extends Operation{
private LightDevice light;
private static String
retvalue = "result";
private static String ns = "ns”;
Exactly the name of the action
declared in the sbl
public OnOperation(LightDevice lightdev){
super("turnOn",new QName("BasicService", ns));
light = lightdev;
Element result = new Element(new QName(retvalue, ns), SchemaUtil.getSchemaType(SchemaUtil.TYPE_STRING));
this.setOutput(result);
}
@Override
public ParameterValue invoke(ParameterValue pv) throws InvocationException {
System.out.println("Light is on!");
boolean ret = light.on();
ParameterValue result = createOutputValue();
if (ret){
ParameterUtil.setString(result, "reply","true");
}
else{
ParameterUtil.setString(result, "reply","false");
}
return result;
}
Call to the on method of
LightDevice (protocol-specific)
The service archive
• Thanks to the WSDL of the service, the client can make syntactically
correct invocations of the operations
• A client of our lamp service can retrieve its rich description by
invoking a specific WS operation: GetServiceArchive.
• The latter return a zip file containing
– The variable type declaration (light_level.vml.xml)
– The variable instance declaration (light-variable.vdd.xml)
– The behaviour description (light_type.sbl.xml)
• At this point the client knows the behaviour of a lamp and can make
semantically correct invocations of the operations.
– For example it knows that if the service is in conversational state B
then it should not invoke the turnOff operation
– and if it invokes the turnOn operation the value of the light variable
will be 1 (it knows how an operation affects the environment)
GetServiceArchieveOperation
public class GetServiceArchiveOperation extends Operation{
private static String
retvalue = "result";
private static String ns = "ns" ;
public GetServiceArchiveOperation(){
super("getServiceArchive",new QName("BasicService", ns));
ComplexType rqComplex = new ComplexType(new QName("AttachmentType", ns),
ComplexType.CONTAINER_SEQUENCE);
rqComplex.addElement(new Element(new QName("File", ns),
SchemaUtil.getSchemaType(SchemaUtil.TYPE_BASE64_BINARY)));
Element messageOUT = new Element(new QName("AttachmentMsg", ns));
messageOUT.setType(rqComplex);
this.setOutput(messageOUT);
}
public ParameterValue invoke(ParameterValue pv) throws InvocationException {
System.out.println("Get service archive invoked!!!");
ParameterValue result = createOutputValue();
try {
ParameterUtil.setAttachment(result, "File",
DPWSFramework.getAttachmentFactory().createFileAttachment("resources/service_archive/BedroomLight.zip", "application/zip"));
} catch (IOException e) {
System.out.println(e.getMessage());
}
return result;
}
}
An Attachment is binary data which is attached to a SOAP message.
The attachment isn’t transmitted inline the SOAP part of the message,
but appended to the SOAP message by the use of the MIME format.
Client-server interaction
Client
DPWSLight
“Hello”
syntax
GetServiceArchive
syntax +
semanthics
Service archive (zip file)
GetState
State = A
turnOff
Asynchronous events
• So far we have seen only synchronous operations
to retrieve the state/variable of our lamp.
– A client can invoke the turnOn operation and, when
the operation returns, it can check the conversational
state by invoking the GetState operation
• What happens if a user in the house presses a
wall mounted light switch controlling the lamp?
– The service must be aware of the event and change its
internal representation of the device
Asynchronous events
public class LightDevice implements BusIndicationListener{
…
@Override
public void onIndication(BusEventIndication bei) {
logger.info(bei.toString());
if(bei.getValue()==100){
variable.setValueOn();
state.setStateA();
notifyState();
notifyValue();
}
else{
if(bei.getValue()==0){
variable.setValueOff();
state.setStateB();
notifyState();
notifyValue();
}
}
}
…
private void notifyValue(){
Iterator<VariableChangedListener> it = valueListeners.iterator();
logger.info("Notifying the change of value to all the listeners");
while (it.hasNext()){
VariableChangedListener currentListener = it.next();
logger.fine("Notifying to listener: " + currentListener.getClass().getName());
currentListener.VariableChanged(variable);
}
}
Asynchronous events
DefaultEventSource
1..1
1..1
DPWSLight
1..1
LightService
1..1
State
LightDevice
1..1
Variable
SimpleValueNotifica
tion
Client
(subscribed
to the event
source)
Clients
• Thanks to DPWS libraries you can develop a
custom client able to track the service
dynamically, invoke operations and detect
events.
• But now we will see a generic and universal
DPWS client in action…
Device
Service
PortTypes
DPWS Explorer Endpoint reference
Operations
http://ws4d.e-technik.uni-rostock.de/dpws-explorer/
Download