Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add some different xPL implementations done by Telldus

  • Loading branch information...
commit d4b46c71ece3f1c62233f1487f45181937387016 1 parent deebf20
@mickeprag mickeprag authored
View
371 xpl/data/uml.xmi
@@ -0,0 +1,371 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI verified="false" xmi.version="1.2" timestamp="2009-08-20T21:13:04" xmlns:UML="http://schema.omg.org/spec/UML/1.3" >
+ <XMI.header>
+ <XMI.documentation>
+ <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+ <XMI.exporterVersion>1.5.8</XMI.exporterVersion>
+ <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+ </XMI.documentation>
+ <XMI.metamodel xmi.version="1.3" href="UML.xml" xmi.name="UML" />
+ </XMI.header>
+ <XMI.content>
+ <UML:Model isSpecification="false" isAbstract="false" isLeaf="false" xmi.id="m1" isRoot="false" name="UML Model" >
+ <UML:Namespace.ownedElement>
+ <UML:Stereotype visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="folder" name="folder" />
+ <UML:Stereotype visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="datatype" name="datatype" />
+ <UML:Stereotype visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="enum" name="enum" />
+ <UML:Model stereotype="folder" visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Logical View" name="Logical View" >
+ <UML:Namespace.ownedElement>
+ <UML:Package stereotype="folder" visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Datatypes" name="Datatypes" >
+ <UML:Namespace.ownedElement>
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="IGSdGv66Dl0t" name="int" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="U4XSIE3QJ6hx" name="char" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="wqDoP5wfLOIc" name="bool" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="HMiS7gMcit21" name="float" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="63PN95L5vWtI" name="double" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="bnxw9DWQZCtg" name="short" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="sDGZ4IaALxYS" name="long" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="2rVxNPDwAAqK" name="unsigned int" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="NNkuXbbOmpxp" name="unsigned short" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="8XzRUVsXMNSh" name="unsigned long" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="kedvoSFAnx4K" name="string" />
+ <UML:DataType stereotype="datatype" visibility="public" isSpecification="false" namespace="Datatypes" isAbstract="false" isLeaf="false" elementReference="dvT79RUD0eZq" isRoot="false" xmi.id="blfxn9Uuu2yR" name="Map&lt;string, string>" />
+ </UML:Namespace.ownedElement>
+ </UML:Package>
+ <UML:Class visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="XdiJTf8ZA6yd" name="xPLMessage" >
+ <UML:Classifier.feature>
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="Oy4sMfnqmwFE" type="blfxn9Uuu2yR" name="body" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="7Dsh3RQhMBqr" type="IGSdGv66Dl0t" name="hop" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="o7d2CrsruJHZ" type="kedvoSFAnx4K" name="source" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="fRQUU8LUIdpp" type="kedvoSFAnx4K" name="target" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="tCGUEQs0VW0i" type="ZqAwEabwEDr1" name="identifier" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="HHoVQbGDrTVa" type="kedvoSFAnx4K" name="messageSchemeIdentifier" />
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="IvRClCZ1LX9n" name="xPLMessage" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="fqxUu37A4RS3" type="ZqAwEabwEDr1" value="" name="identifier" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="uUirWhfMjnAf" name="addBodyItem" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="5UmJmRq4exRu" type="kedvoSFAnx4K" value="" name="key" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="gUweefMhDcVo" type="kedvoSFAnx4K" value="" name="value" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Ujr3jkVCgowi" name="addHeadItem" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="M6EhfsocNMwl" type="kedvoSFAnx4K" value="" name="key" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="vB79kv7SfBkB" type="kedvoSFAnx4K" value="" name="value" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Zvm4WIb2Z2yx" name="bodyItem" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="rqKcz5n6oSXF" type="kedvoSFAnx4K" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="0U12xzu7s4bX" name="setMessageSchemeIdentifier" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="0baZghhFr2Gt" type="ZqAwEabwEDr1" value="" name="msi" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="IjmpHLdfT2KV" name="setSource" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="rmmDgsIsGvAe" type="kedvoSFAnx4K" value="" name="value" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="5F2P6cAAbBHb" name="setTarget" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="SpoO35A5dPta" type="kedvoSFAnx4K" value="" name="value" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="rfXl2OnJiltE" name="source" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="WAMYNo0vYq2M" type="kedvoSFAnx4K" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="qZIqOH4DSRXm" name="target" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="w1rngMZgkKzR" type="kedvoSFAnx4K" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="tM3YAlRVdQgs" name="toString" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="5XkHvMEmhb5n" type="kedvoSFAnx4K" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" ownerScope="classifier" isRoot="false" xmi.id="MKlnQwQyMUPk" name="createMessageFromString" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="dHW4EsYbaZuh" type="XdiJTf8ZA6yd" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="ZN62oiIzXjU7" type="kedvoSFAnx4K" value="" name="message" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Enumeration stereotype="enum" visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="ZqAwEabwEDr1" name="Identifier" >
+ <UML:EnumerationLiteral visibility="public" isSpecification="false" namespace="ZqAwEabwEDr1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="a2Smc4ipHYou" name="xpl-cmnd" />
+ <UML:EnumerationLiteral visibility="public" isSpecification="false" namespace="ZqAwEabwEDr1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="gnMEpp0PriC6" name="xpl-stat" />
+ <UML:EnumerationLiteral visibility="public" isSpecification="false" namespace="ZqAwEabwEDr1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="R3WGxP4bAOpz" name="xpl-trig" />
+ </UML:Enumeration>
+ <UML:Class visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="dvT79RUD0eZq" name="Map" />
+ <UML:Class visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="4xTqfjoBSIIy" name="xPLInstance" >
+ <UML:Classifier.feature>
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="gzfxVRaEH2yu" type="EhAjKT6PpPv2" name="thisDevice" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="6hYNhUIrbCdr" type="EhAjKT6PpPv2" name="devices[]" />
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="ijPzFRB6xmeW" name="xPLInstance" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="CHVlflsSjf9B" type="EhAjKT6PpPv2" value="" name="device" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="QBcO7FmfSSb5" name="xPLInstance" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="RTrVOEMT27QK" type="kedvoSFAnx4K" value="" name="vendor" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="pZAPjjbo64Jc" type="kedvoSFAnx4K" value="" name="device" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="wveG7Ynvnhnk" name="attatched" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="luTzkEVhEVCS" type="wqDoP5wfLOIc" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="6ZLoecJsWISz" name="detach" />
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="G2jy7qV2pA4v" name="devices" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="3jSGxUztZpPb" type="EhAjKT6PpPv2" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="lFdgofbt1M6S" name="sendMessage" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="hnmruig0iw66" type="XdiJTf8ZA6yd" value="" name="message" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="protected" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="bCE0DS6qC5QW" name="attatchedToNetwork" />
+ <UML:Operation visibility="protected" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="moaxEeoRjCxr" name="handleMessage" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="LD8G4G2pzErD" type="wqDoP5wfLOIc" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="9V85HisHjStJ" type="XdiJTf8ZA6yd" value="" name="message" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Class visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="EhAjKT6PpPv2" name="xPLDevice" >
+ <UML:Classifier.feature>
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="5LzeZ6f1a24e" type="kedvoSFAnx4K" name="vendor" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="r7p70tyF8bH0" type="kedvoSFAnx4K" name="device" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="gvkX0lhPYP5H" type="kedvoSFAnx4K" name="instance" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="sawPoTW1GCXN" type="kedvoSFAnx4K" name="address" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="st4NSOrILO1a" type="IGSdGv66Dl0t" name="heartbeatInterval" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="1PNIBOyUoUUx" type="IGSdGv66Dl0t" name="port" />
+ <UML:Attribute visibility="private" isSpecification="false" xmi.id="jU2f3VMLHg33" type="P9JIMGtNBq3k" name="lastHeartBeat" />
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="uHpYNKyBWovy" name="xPLDevice" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="qRHXZ0q35DqS" type="kedvoSFAnx4K" value="" name="vendor" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="8soItGDA5jYO" type="kedvoSFAnx4K" value="" name="device" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="ihuWcqZSIoyr" type="kedvoSFAnx4K" value="" name="instance" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="pmsszjK7Z9NS" name="xPLDevice" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="NYbQI7oymhSN" type="kedvoSFAnx4K" value="" name="vendor" />
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="X1nnnldaVVSU" type="kedvoSFAnx4K" value="" name="device" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="rxv2JOVkHT5S" name="address" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="6sTypq4ddy6C" type="kedvoSFAnx4K" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="gowBqombL9ae" name="heartBeatInterval" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="gim7k4LmGj6g" type="IGSdGv66Dl0t" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="1HoixgmuU10N" name="deviceName" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="PL0k7PSvf2Gm" type="kedvoSFAnx4K" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="BIvEFJyCZGpO" name="lastHeartBeat" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="56bP90wqKGUp" type="P9JIMGtNBq3k" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="true" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="CUdVuyok5Btg" name="port" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter kind="return" xmi.id="lWuymn7SufRD" type="IGSdGv66Dl0t" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="4RXtnfpZOlly" name="setAddress" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="1MJSZetHX46j" type="kedvoSFAnx4K" value="" name="address" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="jDamtEfHNoSK" name="setHeartBeatInterval" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="MSTbJJwgWBKp" type="IGSdGv66Dl0t" value="" name="minutes" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="la9uc1o3SziP" name="setLastHeartbeat" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="PEdHSGRODs9y" type="P9JIMGtNBq3k" value="" name="timestamp" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation visibility="public" isSpecification="false" isQuery="false" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="nQWXNeQsFSEb" name="setPort" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter visibility="private" isSpecification="false" xmi.id="z1XnDSALsQqX" type="IGSdGv66Dl0t" value="" name="port" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Enumeration stereotype="enum" visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="ioL5YhpoYAWd" name="OperationMode" >
+ <UML:EnumerationLiteral visibility="public" isSpecification="false" namespace="ioL5YhpoYAWd" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="7C7bDTwbQv2H" name="Client" />
+ <UML:EnumerationLiteral visibility="public" isSpecification="false" namespace="ioL5YhpoYAWd" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="DQHpEraw64eW" name="Disconnected" />
+ <UML:EnumerationLiteral visibility="public" isSpecification="false" namespace="ioL5YhpoYAWd" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="MsihEUMf7fjn" name="Hub" />
+ </UML:Enumeration>
+ <UML:Class visibility="public" isSpecification="false" namespace="Logical View" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="P9JIMGtNBq3k" name="datetime" />
+ </UML:Namespace.ownedElement>
+ <XMI.extension xmi.extender="umbrello" >
+ <diagrams>
+ <diagram showopsig="1" linecolor="#ff0000" snapx="10" showattribassocs="1" snapy="10" linewidth="0" showattsig="1" showpubliconly="0" showpackage="1" showstereotype="1" name="class diagram" font="Sans Serif,10,-1,0,50,0,0,0,0,0" canvasheight="801" canvaswidth="1075" localid="" snapcsgrid="0" showgrid="0" showops="1" usefillcolor="1" fillcolor="#ffff00" zoom="100" xmi.id="hb855HgsAFsZ" documentation="" showscope="1" snapgrid="0" showatts="1" type="1" >
+ <widgets>
+ <classwidget linecolor="#ff0000" usesdiagramfillcolor="0" linewidth="none" showoperations="1" usesdiagramusefillcolor="0" showpubliconly="0" showpackage="1" x="86" showattsigs="601" showstereotype="1" y="55" showattributes="1" font="Sans Serif,10,-1,5,75,0,0,0,0,0" width="401" isinstance="0" usefillcolor="1" fillcolor="#ffff00" xmi.id="XdiJTf8ZA6yd" showscope="1" height="288" showopsigs="601" />
+ <enumwidget width="79" showstereotype="1" x="546" y="54" usesdiagramusefillcolor="1" usesdiagramfillcolor="1" isinstance="0" fillcolor="none" height="80" linecolor="none" xmi.id="ZqAwEabwEDr1" showpackage="1" usefillcolor="1" linewidth="none" font="Sans Serif,10,-1,0,50,0,0,0,0,0" />
+ <classwidget linecolor="#ff0000" usesdiagramfillcolor="0" linewidth="none" showoperations="1" usesdiagramusefillcolor="0" showpubliconly="0" showpackage="1" x="106" showattsigs="601" showstereotype="1" y="380" showattributes="1" font="Sans Serif,10,-1,5,75,0,0,0,0,0" width="324" isinstance="0" usefillcolor="1" fillcolor="#ffff00" xmi.id="4xTqfjoBSIIy" showscope="1" height="176" showopsigs="601" />
+ <classwidget linecolor="#ff0000" usesdiagramfillcolor="0" linewidth="none" showoperations="1" usesdiagramusefillcolor="0" showpubliconly="0" showpackage="1" x="529" showattsigs="601" showstereotype="1" y="180" showattributes="1" font="Sans Serif,10,-1,5,50,0,0,0,0,0" width="399" isinstance="0" usefillcolor="1" fillcolor="#ffff00" xmi.id="EhAjKT6PpPv2" showscope="1" height="304" showopsigs="601" />
+ </widgets>
+ <messages/>
+ <associations>
+ <assocwidget indexa="1" indexb="1" visibilityA="0" widgetaid="XdiJTf8ZA6yd" visibilityB="0" linecolor="none" changeabilityA="900" totalcounta="2" xmi.id="tCGUEQs0VW0i" changeabilityB="900" widgetbid="ZqAwEabwEDr1" totalcountb="2" type="510" linewidth="none" >
+ <linepath>
+ <startpoint startx="487" starty="115" />
+ <endpoint endx="546" endy="115" />
+ </linepath>
+ <floatingtext linecolor="none" usesdiagramfillcolor="1" linewidth="none" usesdiagramusefillcolor="1" x="482" showstereotype="1" y="117" text="identifier" font="Sans Serif,10,-1,0,50,0,0,0,0,0" pretext="-" role="710" width="66" isinstance="0" posttext="" usefillcolor="1" fillcolor="none" xmi.id="NcywuLejcB4E" height="22" />
+ </assocwidget>
+ <assocwidget indexa="1" indexb="1" visibilityA="0" widgetaid="4xTqfjoBSIIy" visibilityB="0" linecolor="none" changeabilityA="900" totalcounta="3" xmi.id="gzfxVRaEH2yu" changeabilityB="900" widgetbid="EhAjKT6PpPv2" totalcountb="3" type="510" linewidth="none" >
+ <linepath>
+ <startpoint startx="430" starty="432" />
+ <endpoint endx="529" endy="432" />
+ </linepath>
+ <floatingtext linecolor="none" usesdiagramfillcolor="1" linewidth="none" usesdiagramusefillcolor="1" x="452" showstereotype="1" y="400" text="thisDevice" font="Sans Serif,10,-1,0,50,0,0,0,0,0" pretext="-" role="710" width="77" isinstance="0" posttext="" usefillcolor="1" fillcolor="none" xmi.id="dUkwuSZTB6bL" height="22" />
+ </assocwidget>
+ <assocwidget indexa="2" indexb="2" visibilityA="0" widgetaid="4xTqfjoBSIIy" visibilityB="0" linecolor="none" changeabilityA="900" totalcounta="3" xmi.id="6hYNhUIrbCdr" changeabilityB="900" widgetbid="EhAjKT6PpPv2" totalcountb="3" type="510" linewidth="none" >
+ <linepath>
+ <startpoint startx="430" starty="432" />
+ <endpoint endx="529" endy="432" />
+ </linepath>
+ <floatingtext linecolor="none" usesdiagramfillcolor="1" linewidth="none" usesdiagramusefillcolor="1" x="459" showstereotype="1" y="434" text="devices[]" font="Sans Serif,10,-1,0,50,0,0,0,0,0" pretext="-" role="710" width="68" isinstance="0" posttext="" usefillcolor="1" fillcolor="none" xmi.id="QBvCzLeKycFq" height="22" />
+ </assocwidget>
+ </associations>
+ </diagram>
+ </diagrams>
+ </XMI.extension>
+ </UML:Model>
+ <UML:Model stereotype="folder" visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Use Case View" name="Use Case View" >
+ <UML:Namespace.ownedElement/>
+ </UML:Model>
+ <UML:Model stereotype="folder" visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Component View" name="Component View" >
+ <UML:Namespace.ownedElement/>
+ </UML:Model>
+ <UML:Model stereotype="folder" visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Deployment View" name="Deployment View" >
+ <UML:Namespace.ownedElement/>
+ </UML:Model>
+ <UML:Model stereotype="folder" visibility="public" isSpecification="false" namespace="m1" isAbstract="false" isLeaf="false" isRoot="false" xmi.id="Entity Relationship Model" name="Entity Relationship Model" >
+ <UML:Namespace.ownedElement/>
+ </UML:Model>
+ </UML:Namespace.ownedElement>
+ </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+ <docsettings viewid="hb855HgsAFsZ" uniqueid="w1rngMZgkKzR" documentation="" />
+ <listview>
+ <listitem open="1" type="800" label="Views" >
+ <listitem open="1" type="801" id="Logical View" >
+ <listitem open="0" type="807" id="hb855HgsAFsZ" label="class diagram" />
+ <listitem open="1" type="813" id="dvT79RUD0eZq" />
+ <listitem open="1" type="813" id="P9JIMGtNBq3k" />
+ <listitem open="1" type="813" id="EhAjKT6PpPv2" >
+ <listitem open="0" type="814" id="5LzeZ6f1a24e" />
+ <listitem open="0" type="814" id="r7p70tyF8bH0" />
+ <listitem open="0" type="814" id="gvkX0lhPYP5H" />
+ <listitem open="0" type="814" id="sawPoTW1GCXN" />
+ <listitem open="0" type="814" id="st4NSOrILO1a" />
+ <listitem open="0" type="814" id="1PNIBOyUoUUx" />
+ <listitem open="0" type="814" id="jU2f3VMLHg33" />
+ <listitem open="0" type="815" id="uHpYNKyBWovy" />
+ <listitem open="0" type="815" id="pmsszjK7Z9NS" />
+ <listitem open="0" type="815" id="rxv2JOVkHT5S" />
+ <listitem open="0" type="815" id="gowBqombL9ae" />
+ <listitem open="0" type="815" id="1HoixgmuU10N" />
+ <listitem open="0" type="815" id="BIvEFJyCZGpO" />
+ <listitem open="0" type="815" id="CUdVuyok5Btg" />
+ <listitem open="0" type="815" id="4RXtnfpZOlly" />
+ <listitem open="0" type="815" id="jDamtEfHNoSK" />
+ <listitem open="0" type="815" id="la9uc1o3SziP" />
+ <listitem open="0" type="815" id="nQWXNeQsFSEb" />
+ </listitem>
+ <listitem open="1" type="813" id="4xTqfjoBSIIy" >
+ <listitem open="0" type="814" id="gzfxVRaEH2yu" />
+ <listitem open="0" type="814" id="6hYNhUIrbCdr" />
+ <listitem open="0" type="815" id="ijPzFRB6xmeW" />
+ <listitem open="0" type="815" id="QBcO7FmfSSb5" />
+ <listitem open="0" type="815" id="wveG7Ynvnhnk" />
+ <listitem open="0" type="815" id="6ZLoecJsWISz" />
+ <listitem open="0" type="815" id="G2jy7qV2pA4v" />
+ <listitem open="0" type="815" id="lFdgofbt1M6S" />
+ <listitem open="0" type="815" id="bCE0DS6qC5QW" />
+ <listitem open="0" type="815" id="moaxEeoRjCxr" />
+ </listitem>
+ <listitem open="1" type="813" id="XdiJTf8ZA6yd" >
+ <listitem open="0" type="814" id="Oy4sMfnqmwFE" />
+ <listitem open="0" type="814" id="7Dsh3RQhMBqr" />
+ <listitem open="0" type="814" id="o7d2CrsruJHZ" />
+ <listitem open="0" type="814" id="fRQUU8LUIdpp" />
+ <listitem open="0" type="814" id="tCGUEQs0VW0i" />
+ <listitem open="0" type="814" id="HHoVQbGDrTVa" />
+ <listitem open="0" type="815" id="IvRClCZ1LX9n" />
+ <listitem open="0" type="815" id="uUirWhfMjnAf" />
+ <listitem open="0" type="815" id="Ujr3jkVCgowi" />
+ <listitem open="0" type="815" id="Zvm4WIb2Z2yx" />
+ <listitem open="0" type="815" id="0U12xzu7s4bX" />
+ <listitem open="0" type="815" id="IjmpHLdfT2KV" />
+ <listitem open="0" type="815" id="5F2P6cAAbBHb" />
+ <listitem open="0" type="815" id="rfXl2OnJiltE" />
+ <listitem open="0" type="815" id="qZIqOH4DSRXm" />
+ <listitem open="0" type="815" id="tM3YAlRVdQgs" />
+ <listitem open="0" type="815" id="MKlnQwQyMUPk" />
+ </listitem>
+ <listitem open="0" type="830" id="Datatypes" >
+ <listitem open="1" type="829" id="blfxn9Uuu2yR" />
+ <listitem open="1" type="829" id="wqDoP5wfLOIc" />
+ <listitem open="1" type="829" id="U4XSIE3QJ6hx" />
+ <listitem open="1" type="829" id="63PN95L5vWtI" />
+ <listitem open="1" type="829" id="HMiS7gMcit21" />
+ <listitem open="1" type="829" id="IGSdGv66Dl0t" />
+ <listitem open="1" type="829" id="sDGZ4IaALxYS" />
+ <listitem open="1" type="829" id="bnxw9DWQZCtg" />
+ <listitem open="1" type="829" id="kedvoSFAnx4K" />
+ <listitem open="1" type="829" id="2rVxNPDwAAqK" />
+ <listitem open="1" type="829" id="8XzRUVsXMNSh" />
+ <listitem open="1" type="829" id="NNkuXbbOmpxp" />
+ </listitem>
+ <listitem open="1" type="831" id="ZqAwEabwEDr1" >
+ <listitem open="0" type="839" id="a2Smc4ipHYou" />
+ <listitem open="0" type="839" id="gnMEpp0PriC6" />
+ <listitem open="0" type="839" id="R3WGxP4bAOpz" />
+ </listitem>
+ <listitem open="1" type="831" id="ioL5YhpoYAWd" >
+ <listitem open="0" type="839" id="7C7bDTwbQv2H" />
+ <listitem open="0" type="839" id="DQHpEraw64eW" />
+ <listitem open="0" type="839" id="MsihEUMf7fjn" />
+ </listitem>
+ </listitem>
+ <listitem open="1" type="802" id="Use Case View" />
+ <listitem open="1" type="821" id="Component View" />
+ <listitem open="1" type="827" id="Deployment View" />
+ <listitem open="1" type="836" id="Entity Relationship Model" />
+ </listitem>
+ </listview>
+ <codegeneration>
+ <codegenerator language="C++" />
+ </codegeneration>
+ </XMI.extensions>
+</XMI>
View
21 xpl/phpxpl/example.php
@@ -0,0 +1,21 @@
+<?php
+
+require_once 'xpllighting.class.php';
+
+$xplinstance = new XPLLighting('192.168.0.50');
+
+$running = true;
+declare(ticks = 1) {
+ pcntl_signal( SIGINT, 'signalHandler' );
+ while($running) {
+ if ($xplinstance->doEvents()) {
+ usleep(100);
+ }
+ }
+ $xplinstance->detach();
+}
+
+function signalHandler() {
+global $running;
+ $running = false;
+}
View
66 xpl/phpxpl/xpldevice.class.php
@@ -0,0 +1,66 @@
+<?php
+define('DEFAULT_HBEAT_INTERVAL', 5);
+
+class xPLDevice {
+
+ private $_heartBeatInterval = DEFAULT_HBEAT_INTERVAL;
+ private $_port = 0;
+ private $_vendor = '';
+ private $_device = '';
+ private $_instance = '';
+ private $_address = '';
+ private $_lastHeartBeat = 0;
+
+ public function __construct( $vendor, $device = null ) {
+ if (is_null($device)) {
+ $dash = strpos($vendor, '-');
+ $dot = strpos($vendor, '.');
+ $this->_vendor = substr($vendor, 0, $dash);
+ $this->_device = substr($vendor, $dash+1, $dot-$dash-1);
+ $this->_instance = substr($vendor, $dot+1);
+ } else {
+ $this->_vendor = $vendor;
+ $this->_device = $device;
+
+ //Generate an instance
+ $randomNumber = mt_rand(1, 9999); //Generate ranom number between 1-9999
+ $this->_instance = sprintf('default%s', $randomNumber);
+ }
+ }
+
+ public function address() {
+ return $this->_address;
+ }
+
+ public function heartBeatInterval() {
+ return $this->_heartBeatInterval;
+ }
+
+ public function deviceName() {
+ return sprintf('%s-%s.%s', $this->_vendor, $this->_device, $this->_instance);
+ }
+
+ public function lastHeartBeat() {
+ return $this->_lastHeartBeat;
+ }
+
+ public function port() {
+ return $this->_port;
+ }
+
+ public function setAddress( $address ) {
+ $this->_address = $address;
+ }
+
+ public function setHeartBeatInterval( $minutes ) {
+ $this->_heartBeatInterval = $minutes;
+ }
+
+ public function setPort( $p ) {
+ $this->_port = $p;
+ }
+
+ public function setLastHeartBeat( $timestamp ) {
+ $this->_lastHeartBeat = $timestamp;
+ }
+}
View
210 xpl/phpxpl/xplinstance.class.php
@@ -0,0 +1,210 @@
+<?php
+
+require_once 'xplmessage.class.php';
+require_once 'xpldevice.class.php';
+
+define( XPL_PORT, 3865 );
+
+class XPLInstance {
+ protected $_thisDevice = null;
+ protected $_devices = array();
+
+ private $_socket;
+ private $_isAttached = false;
+ private $_ip;
+
+ public function __construct($vendor, $device, $ip) {
+ $this->_ip = $ip;
+ $this->_thisDevice = new XPLDevice($vendor, $device);
+
+ $this->init();
+ }
+
+ public function attatched() {
+ return $this->_isAttatched;
+ }
+
+ public function detach() {
+ $message = new xPLMessage( xPLMessage::xplstat );
+ $message->setMessageSchemeIdentifier( 'hbeat.end' );
+ $message->setTarget('*');
+ $message->setSource( $this->_thisDevice->deviceName() );
+ $this->sendMessage( $message );
+ socket_close($this->_socket);
+ $this->_socket = null;
+ }
+
+ public function doEvents() {
+ $string = socket_read( $this->_socket, 1500);
+ if ($string != '') {
+ $message = XPLMessage::createMessageFromString($string);
+ if ($message) {
+ $this->processMessage( $message );
+ }
+ return false;
+ }
+ $this->poll();
+ return true;
+ }
+
+ public function sendMessage( $message, $device = null ) {
+ //echo "Sending heartbeat\n";
+ $msg = (string)$message;
+ socket_sendto( $this->_socket, $msg, strlen($msg), 0, '255.255.255.255', XPL_PORT );
+ }
+
+ protected function attatchedToNetwork() {
+ }
+
+ protected function handleMessage( $message ) {
+ return false;
+ }
+
+
+ private function bindToPort() {
+ $port = 49152;
+ //$port = XPL_PORT;
+ $error = 98;
+ while ($error == 98 && $port < 65535) {
+ if (@socket_bind($this->_socket, $this->_ip, $port) === false) {
+ ++$port;
+ } else {
+ echo "Bind succeded as client on: " . $port . "\n";
+ return $port;
+ }
+ }
+ return 0;
+ }
+
+ private function init() {
+ if (($this->_socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === false) {
+ echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
+ return;
+ }
+
+ socket_set_option( $this->_socket, SOL_SOCKET, SO_BROADCAST, 1);
+ socket_set_nonblock( $this->_socket );
+
+ $this->_thisDevice->setPort( $this->bindToPort() );
+ if ($this->_thisDevice->port() == 0) {
+ echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($this->_socket)) . "\n";
+ return;
+ }
+
+ printf("xPL server started (bound to port %s)\n", $this->_thisDevice->port());
+ $this->sendHeartbeat();
+ }
+
+ private function poll() {
+ if (!$this->attatched()) {
+ $this->sendHeartbeat();
+ return;
+ }
+
+ if (time()-$this->_thisDevice->lastHeartBeat() >= $this->_thisDevice->heartBeatInterval() * 60) {
+ $this->sendHeartbeat();
+ }
+ //Loop all devices to see if they have timed out
+ foreach( $this->_devices as $key => $device ) {
+ if ( time()-$device->lastHeartBeat() >= $device->heartBeatInterval() * 60 * 2) {
+ printf("Device removed (timeout): %s\n", $device->deviceName());
+
+ //This is not a prefeered way of removing the item from an array
+ //Since we are iterating the loop will miss to check the new item.
+ //Here, it will be checked next time poll is called
+ unset($this->_devices[$key]);
+ continue;
+ }
+ }
+ }
+
+ private function processHeartBeat( $message ) {
+ if ($message->messageSchemeIdentifier() == 'hbeat.request') {
+ $this->sendHeartbeat();
+ return true;
+ }
+ foreach( $this->_devices as $key => $device ) {
+ if ( $device->deviceName() == $message->source() ) {
+ if (substr($message->messageSchemeIdentifier(), -3) == 'end') {
+ echo "Device removed: " . $message->source() . "\n";
+ unset($this->_devices[$key]);
+ return true;
+ } else {
+ $device->setLastHeartBeat( time() );
+ $device->setHeartBeatInterval( $message->bodyItem( 'interval' ) );
+ }
+ return true;
+ }
+ }
+ if ( (substr($message->messageSchemeIdentifier(), -3) != 'app') && (substr($message->messageSchemeIdentifier(), -5) != 'basic') ) { //Not a heartbeat
+ return false;
+ }
+
+ printf( "New device: %s\n", $message->source() );
+ $device = new xPLDevice( $message->source() );
+ $device->setHeartBeatInterval( $message->bodyItem('interval') );
+ $device->setLastHeartBeat( time() );
+ if ($message->messageSchemeIdentifier() == 'hbeat.app') {
+ $device->setAddress( $message->bodyItem('remote-ip'));
+ $device->setPort( $message->bodyItem('port') );
+ }
+ $this->_devices[] = $device;
+ return true;
+ }
+
+ private function processMessage( $message ) {
+ if (!$this->attatched() && $message->messageSchemeIdentifier() == 'hbeat.app' && $message->source() == $this->_thisDevice->deviceName()) {
+ //Our own echo
+ $this->setAttatched( true );
+ return;
+ }
+ if ($message->source() == $this->_thisDevice->deviceName()) {
+ //Ignore messages from ourselves
+ return;
+ }
+ if ( (substr($message->messageSchemeIdentifier(), 0, 5) == 'hbeat') || (substr($message->messageSchemeIdentifier(), 0, 6) == 'config') ) {
+ if ($this->processHeartBeat( $message )) {
+ return;
+ }
+ }
+ if ($message->target() != $this->_thisDevice->deviceName() && $message->target() != '*') {
+ //Message not for us
+ return;
+ }
+ if (!$this->handleMessage($message)) {
+ printf("Got message:\n%s", $message);
+ }
+ }
+
+
+ private function sendHeartbeat() {
+// echo "Sending heartbeat\n";
+ $message = new xPLMessage( xPLMessage::xplstat );
+ $message->setMessageSchemeIdentifier( 'hbeat.app' );
+ $message->setTarget('*');
+ $message->setSource( $this->_thisDevice->deviceName() );
+ $message->addBodyItem( 'interval', $this->_thisDevice->heartBeatInterval() );
+ $message->addBodyItem( 'port', $this->_thisDevice->port() );
+ $message->addBodyItem( 'remote-ip', $this->_ip );
+ $this->sendMessage( $message );
+ $this->_thisDevice->setLastHeartBeat( time() );
+ }
+
+ private function setAttatched( $attatched ) {
+ $this->_isAttatched = $attatched;
+ if ($this->_isAttatched) {
+ echo "Attatched to xPL-network\n";
+// timer->setInterval( 60000 ); //Once a minute
+
+ $message = new xPLMessage( xPLMessage::xplcmnd );
+ $message->setTarget( "*" );
+ $message->setSource( $this->_thisDevice->deviceName() );
+ $message->setMessageSchemeIdentifier( 'hbeat.request' );
+ $message->addBodyItem('command', 'request');
+ $this->sendMessage( $message );
+
+ $this->attatchedToNetwork();
+ }
+ }
+
+}
View
172 xpl/phpxpl/xpllighting.class.php
@@ -0,0 +1,172 @@
+<?php
+
+require_once 'xplinstance.class.php';
+
+class xPLLighting extends XPLInstance {
+
+ public function __construct($ip) {
+ parent::__construct('telldus', 'core', $ip);
+ }
+
+ protected function attatchedToNetwork() {
+ $message = new xPLMessage( xPLMessage::xpltrig );
+ $message->setMessageSchemeIdentifier( 'lighting.gateway' );
+ $message->setTarget('*');
+ $message->setSource( $this->_thisDevice->deviceName() );
+ $message->addBodyItem( 'report', 'gateway-ready' );
+ $this->sendMessage( $message );
+ }
+
+ protected function handleMessage( $message ) {
+ if ($message->messageSchemeIdentifier() == 'lighting.request') {
+ return $this->lightingRequest($message);
+ }
+ return false;
+ }
+
+ private function lightingRequest( $message ) {
+ switch( $message->bodyItem('request') ) {
+ case 'gateinfo':
+ return $this->gateInfo( );
+ case 'netlist':
+ return $this->netList( );
+ case 'netinfo':
+ return $this->netInfo( $message );
+ case 'devlist':
+ return $this->devList( $message );
+ case 'devinfo':
+ return $this->devInfo( $message );
+ }
+ return false;
+ }
+
+ private function gateInfo( ) {
+ $message = new xPLMessage( xPLMessage::xplstat );
+ $message->setMessageSchemeIdentifier( 'lighting.gateinfo' );
+ $message->setTarget('*');
+ $message->setSource( $this->_thisDevice->deviceName() );
+ $message->addBodyItem( 'status', 'ok' );
+ $message->addBodyItem( 'protocol', 'TELLDUS' );
+ $message->addBodyItem( 'description', 'xPL to Telldus TellStick gateway' );
+ $message->addBodyItem( 'version', '1.0' );
+ $message->addBodyItem( 'author', 'Telldus Technologies AB' );
+ $message->addBodyItem( 'info-url', 'http://www.telldus.se' );
+ $message->addBodyItem( 'net-count', '1' );
+ $message->addBodyItem( 'preferred-net', '1' );
+ $message->addBodyItem( 'scenes-ok', 'false' );
+ $message->addBodyItem( 'channels-ok', 'false' );
+ $message->addBodyItem( 'fade-rate-ok', 'false' );
+ $this->sendMessage( $message );
+ return true;
+ }
+
+ private function netList( ) {
+ $message = new xPLMessage( xPLMessage::xplstat );
+ $message->setMessageSchemeIdentifier( 'lighting.netlist' );
+ $message->setTarget('*');
+ $message->setSource( $this->_thisDevice->deviceName() );
+ $message->addBodyItem( 'status', 'ok' );
+ $message->addBodyItem( 'network', '1' );
+ $this->sendMessage( $message );
+ return true;
+ }
+
+ private function netInfo( $message ) {
+ $msg = new xPLMessage( xPLMessage::xplstat );
+ $msg->setMessageSchemeIdentifier( 'lighting.netinfo' );
+ $msg->setTarget('*');
+ $msg->setSource( $this->_thisDevice->deviceName() );
+// print_r($message);
+ $msg->addBodyItem( 'network', $message->bodyItem('network') );
+ if ($msg->bodyItem('network') == '1') {
+ $msg->addBodyItem( 'status', 'ok' );
+ $msg->addBodyItem( 'name', exec('hostname') );
+ $msg->addBodyItem( 'device-count', tdGetNumberOfDevices() );
+ $msg->addBodyItem( 'scene-count', 0 );
+ } else {
+ $msg->addBodyItem( 'status', 'not-found' );
+ }
+ $this->sendMessage( $msg );
+ return true;
+ }
+
+ private function devList( $message ) {
+ $msg = new xPLMessage( xPLMessage::xplstat );
+ $msg->setMessageSchemeIdentifier( 'lighting.devlist' );
+ $msg->setTarget('*');
+ $msg->setSource( $this->_thisDevice->deviceName() );
+ $msg->addBodyItem( 'network', $message->bodyItem('network') );
+ if ($msg->bodyItem('network') == '1') {
+ $msg->addBodyItem( 'status', 'ok' );
+ $count = tdGetNumberOfDevices();
+ $deviceList = array();
+ for( $i = 0; $i < $count; ++$i ) {
+ $deviceList[] = tdGetDeviceId($i);
+ }
+ $msg->addBodyItem( 'device-count', $count );
+ $msg->addBodyItem( 'device', implode(',', $deviceList) );
+ } else {
+ $msg->addBodyItem( 'status', 'not-found' );
+ }
+ $this->sendMessage( $msg );
+ return true;
+ }
+
+ private function devInfo( $message ) {
+ $found = false;
+ $count = tdGetNumberOfDevices();
+ $deviceId = $message->bodyItem('device');
+ for( $i = 0; $i < $count; ++$i ) {
+ if (tdGetDeviceId($i) == $deviceId) {
+ $found = true;
+ break;
+ }
+ }
+
+ $msg = new xPLMessage( xPLMessage::xplstat );
+ $msg->setMessageSchemeIdentifier( 'lighting.devinfo' );
+ $msg->addBodyItem( 'network', $message->bodyItem('network') );
+ $msg->addBodyItem( 'device', $deviceId );
+ $msg->setTarget('*');
+ $msg->setSource( $this->_thisDevice->deviceName() );
+
+ if ($msg->bodyItem('network') == '1' && $found) {
+ $methods = tdMethods($deviceId, TELLDUS_TURNON | TELLDUS_TURNOFF | TELLDUS_DIM );
+ $msg->addBodyItem( 'status', 'ok' );
+ $msg->addBodyItem( 'name', tdGetName($deviceId) );
+ $msg->addBodyItem( 'report-on-manual', 'false' );
+ $msg->addBodyItem( 'channel-count', '1');
+ $msg->addBodyItem( 'primary-channel', '1');
+ $msg->addBodyItem( 'channel', sprintf('1,%s,0,0', ($methods & TELLDUS_DIM ? 'true' : 'false')) );
+ $msg->addBodyItem( 'scene-count', '0');
+ } else {
+ $msg->addBodyItem( 'status', 'not-found' );
+ }
+ $this->sendMessage( $msg );
+ return true;
+ }
+
+ private function scnList( $message ) {
+ $msg = new xPLMessage( xPLMessage::xplstat );
+ $msg->setMessageSchemeIdentifier( 'lighting.scnlist' );
+ $msg->setTarget('*');
+ $msg->setSource( $this->_thisDevice->deviceName() );
+ $msg->addBodyItem( 'network', $message->bodyItem('network') );
+ $msg->addBodyItem( 'status', 'not-found' );
+ $this->sendMessage( $msg );
+ return true;
+ }
+
+ private function scnInfo( $message ) {
+ $msg = new xPLMessage( xPLMessage::xplstat );
+ $msg->setMessageSchemeIdentifier( 'lighting.scninfo' );
+ $msg->addBodyItem( 'network', $message->bodyItem('network') );
+ $msg->addBodyItem( 'scene', $message->bodyItem('scene') );
+ $msg->setTarget('*');
+ $msg->setSource( $this->_thisDevice->deviceName() );
+ $msg->addBodyItem( 'status', 'not-found' );
+ $this->sendMessage( $msg );
+ return true;
+ }
+
+}
View
144 xpl/phpxpl/xplmessage.class.php
@@ -0,0 +1,144 @@
+<?php
+
+class xPLMessage {
+
+ private $_hop = 1;
+ private $_identifier = null;
+ private $_body = array();
+ private $_msi = '';
+ private $_source = '';
+ private $_target = '';
+
+ const xplcmnd = 1;
+ const xplstat = 2;
+ const xpltrig = 3;
+
+ public function __construct($identifier) {
+ $this->_identifier = $identifier;
+ }
+
+ public function addBodyItem( $key, $value ) {
+ $this->_body[$key] = $value;
+ }
+
+ public function addHeadItem( $key, $value ) {
+ if ($key == 'hop') {
+ $hop = (int)$value;
+ } else if ($key == 'source') {
+ $this->setSource($value);
+ } else if ($key == 'target') {
+ $this->setTarget($value);
+ }
+ }
+
+ public function bodyItem( $key ) {
+ if (array_key_exists($key, $this->_body)) {
+ return $this->_body[$key];
+ }
+ return '';
+ }
+
+ public function messageSchemeIdentifier() {
+ return $this->_msi;
+ }
+
+ public function source() {
+ return $this->_source;
+ }
+
+ public function target() {
+ return $this->_target;
+ }
+
+ public function setMessageSchemeIdentifier( $messageSchemeIdentifier ) {
+ $this->_msi = $messageSchemeIdentifier;
+ }
+
+ public function setSource( $value ) {
+ $this->_source = $value;
+ }
+
+ public function setTarget( $value ) {
+ $this->_target = $value;
+ }
+
+ public function __tostring() {
+ $message = '';
+
+ switch( $this->_identifier ) {
+ case self::xplcmnd:
+ $message .= "xpl-cmnd\n";
+ break;
+ case self::xplstat:
+ $message .= "xpl-stat\n";
+ break;
+ case self::xpltrig:
+ $message .= "xpl-trig\n";
+ break;
+ default:
+ return "";
+ }
+
+ $message .= "{\n";
+ $message .= sprintf("hop=%s\n", $this->_hop);
+ $message .= sprintf("source=%s\n", $this->_source);
+ $message .= sprintf("target=%s\n", $this->_target);
+ $message .= "}\n";
+ $message .= $this->_msi . "\n";
+ $message .= "{\n";
+ foreach( $this->_body as $key => $value ) {
+ $message .= sprintf("%s=%s\n", $key, $value);
+ }
+ $message .= "}\n";
+
+ return $message;
+ }
+
+ public static function createMessageFromString( $message ) {
+ $lines = explode("\n", $message);
+ $row = 0;
+
+ $i = 0;
+
+ if ($lines[$row] == 'xpl-cmnd') {
+ $i = self::xplcmnd;
+ } else if ($lines[$row] == 'xpl-stat') {
+ $i = self::xplstat;
+ } else if ($lines[$row] == 'xpl-trig') {
+ $i = self::xpltrig;
+ } else {
+ return 0;
+ }
+ ++$row;
+
+ if ($lines[$row] != '{') {
+ return 0;
+ }
+ ++$row;
+
+ $msg = new xPLMessage($i);
+ for(; $row < count($lines) && $lines[$row] != '}'; ++$row) {
+ list($name, $value) = explode( '=', $lines[$row] );
+ $msg->addHeadItem( $name, $value );
+ }
+ if ($row >= count($lines)) {
+ return 0;
+ }
+ ++$row;
+
+ $msg->setMessageSchemeIdentifier( $lines[$row] );
+ ++$row;
+
+ if ($lines[$row] != '{') {
+ return 0;
+ }
+ ++$row;
+
+ for(; $row < count($lines) && $lines[$row] != '}'; ++$row) {
+ list($name, $value) = explode( '=', $lines[$row] );
+ $msg->addBodyItem( $name, $value );
+ }
+
+ return $msg;
+ }
+}
View
1  xpl/pyxpl/__init__.py
@@ -0,0 +1 @@
+__all__ = ["xplmessage", "xpldevice", "xplinstance"]
View
22 xpl/pyxpl/xpldevice.py
@@ -0,0 +1,22 @@
+###########################################################################
+# Copyright (C) 2009 by Magnus Ahlberg
+# <magnus.ahlberg@svart-katt.se>
+#
+# Copyright: See COPYING file that comes with this distribution
+#
+###########################################################################
+
+class XPLDevice:
+ """A class to manage and xPL device"""
+ vendor = ""
+ device = ""
+ instance = ""
+
+ def __init__(devicename):
+ pass
+
+ def __init__(vendor, device):
+ pass
+
+ def __init__(vendor, device, instance):
+ pass
View
47 xpl/pyxpl/xplinstance.py
@@ -0,0 +1,47 @@
+###########################################################################
+# Copyright (C) 2009 by Magnus Ahlberg
+# <magnus.ahlberg@svart-katt.se>
+#
+# Copyright: See COPYING file that comes with this distribution
+#
+###########################################################################
+
+from xpldevice import *
+
+from socket import *
+
+class XPLInstance:
+ """Class to handle an xPL session"""
+ MODE_UNDEFINED, MODE_CLIENT, MODE_DISCONNECTED, MODE_HUB = range(4)
+
+ __thisDevice = XPLDevice()
+ __devices = ()
+ __mode = MODE_UNDEFINED
+
+ def __init__(self, device):
+ self.__thisDevice = device
+
+ def __init__(self, vendor, deviceName):
+ device = XPLDevice(vendor, deviceName)
+ self.__init__(device)
+
+ def attached(self):
+ pass
+
+ def devices(self):
+ return devices
+
+ def operationMode(self):
+ return operationMode
+
+ def sendMessage(self, message):
+ pass
+
+ def sendMessage(self, message, device):
+ pass
+
+ def shutdown(self):
+ pass
+
+ def bindToPort(self):
+ pass
View
56 xpl/pyxpl/xplmessage.py
@@ -0,0 +1,56 @@
+###########################################################################
+# Copyright (C) 2009 by Magnus Ahlberg
+# <magnus.ahlberg@svart-katt.se>
+#
+# Copyright: See COPYING file that comes with this distribution
+#
+###########################################################################
+
+class XPLMessage:
+ """A class for managing xPL messages"""
+ ID_UNDEFINED, ID_XPLCMND, ID_XPLSTAT, ID_XPLTRIG = range(4)
+ __body = {}
+ __hop = 0
+ __source = ""
+ __target = ""
+ __identifier = ID_UNDEFINED
+ __identifierString = ("-", "xpl-cmnd", "xpl-stat", "xpl-trig")
+ __messageSchemaIdentifier = ""
+
+ def __init__(self, identifier, messageSchemaIdentifier):
+ self.__identifier = identifier
+ self.__messageSchemaIdentifier = messageSchemaIdentifier
+
+ def addBodyItem(self, key, value):
+ self.__body[key] = value
+
+ def bodyItem(self, key):
+ return self.__body[key]
+
+ def createMessageFromString(message):
+ pass
+
+ def setSource(self, value):
+ self.__source = value
+
+ def setTarget(self, value):
+ self.__target = value
+
+ def toString(self):
+ if self.__identifier == self.ID_UNDEFINED:
+ return ""
+
+ messageStringList = []
+ messageStringList.append(self.__identifierString[self.__identifier] + "\n")
+ messageStringList.append("{\n")
+ messageStringList.append("hop=" + str(self.__hop) + "\n")
+ messageStringList.append("source=" + self.__source + "\n")
+ messageStringList.append("target=" + self.__target + "\n")
+ messageStringList.append("}\n")
+ messageStringList.append(self.__messageSchemaIdentifier + "\n")
+ messageStringList.append("{\n")
+ for key, value in self.__body.iteritems():
+ messageStringList.append(key + "=" + value + "\n")
+ messageStringList.append("}\n")
+
+ return "".join(messageStringList)
View
43 xpl/qtxpl/CMakeLists.txt
@@ -0,0 +1,43 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(qtxpl)
+
+FIND_PACKAGE( Qt4 REQUIRED )
+SET(QT_USE_QTNETWORK TRUE)
+INCLUDE( ${QT_USE_FILE} )
+
+SET( QTXPL_SRCS
+ xpldevice.cpp
+ xplinstance.cpp
+ xplmessage.cpp
+)
+
+SET( QTXPL_HDRS
+ xpldevice.h
+)
+
+SET( QTXPL_MOC_HDRS
+ xplinstance.h
+ xplmessage.h
+)
+
+
+QT4_WRAP_CPP( QTXPL_MOC_SRCS ${QTXPL_MOC_HDRS} )
+QT4_AUTOMOC ( ${QTXPL_SRCS} )
+
+
+SET( QTXPL_LIBRARIES
+ ${QT_LIBRARIES}
+)
+
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+ADD_DEFINITIONS(-DQT_NO_DEBUG)
+
+ADD_LIBRARY("qtxpl" SHARED
+ ${QTXPL_SRCS}
+ ${QTXPL_HDRS}
+ ${QTXPL_MOC_HDRS}
+ ${QTXPL_MOC_SRCS}
+)
+
+TARGET_LINK_LIBRARIES( "qtxpl" ${QTXPL_LIBRARIES} )
+
View
12 xpl/qtxpl/main.cpp
@@ -0,0 +1,12 @@
+#include <QtCore/QCoreApplication>
+
+#include "xplinstance.h"
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+
+ /*xPLInstance *instance = */new xPLInstance("telldus", "center");
+
+ return a.exec();
+}
View
15 xpl/qtxpl/qtxpl.pro
@@ -0,0 +1,15 @@
+# -------------------------------------------------
+# Project created by QtCreator 2009-03-05T16:12:24
+# -------------------------------------------------
+QT += network
+QT -= gui
+TARGET = qtxpl
+CONFIG += console
+CONFIG -= app_bundle
+TEMPLATE = lib
+SOURCES += xpldevice.cpp \
+ xplinstance.cpp \
+ xplmessage.cpp
+HEADERS += xpldevice.h \
+ xplinstance.h \
+ xplmessage.h
View
105 xpl/qtxpl/xpldevice.cpp
@@ -0,0 +1,105 @@
+#include "xpldevice.h"
+
+#include <QDebug>
+#include <stdlib.h>
+#include <time.h>
+
+const int DEFAULT_HBEAT_INTERVAL = 5;
+
+class xPLDevicePrivate {
+public:
+ QString vendor, device, instance;
+ QDateTime lastHeartBeat;
+ int port, heartBeatInterval;
+ QHostAddress address;
+};
+
+xPLDevice::xPLDevice( const xPLDevice &other )
+ : d( new xPLDevicePrivate( *other.d ))
+{
+ //do nothing
+}
+
+xPLDevice& xPLDevice::operator=( xPLDevice other ) {
+ std::swap( this->d, other.d );
+ return *this;
+}
+
+xPLDevice::xPLDevice( const QString &deviceName )
+ :d(new xPLDevicePrivate)
+{
+ d->port = 0;
+ d->heartBeatInterval = DEFAULT_HBEAT_INTERVAL;
+ QString name = deviceName.section('.', 0, 0);
+ d->vendor = name.section('-', 0, 0);
+ d->device = name.section('-', 1, 1);
+ d->instance = deviceName.section('.', 1);
+}
+
+xPLDevice::xPLDevice( const QString &vendor, const QString &device )
+ :d(new xPLDevicePrivate)
+{
+ d->vendor = vendor;
+ d->device = device;
+ d->instance = "";
+ d->port = 0;
+ d->heartBeatInterval = DEFAULT_HBEAT_INTERVAL;
+
+ //Seed the random number generator
+ srand( (unsigned int)time( NULL ) );
+
+ //Generate an instance
+ int randomNumber = rand() % 9999 + 1; //Generate ranom number between 1-9999
+ d->instance = QString("default%1").arg(randomNumber);
+}
+
+xPLDevice::xPLDevice( const QString &vendor, const QString &device, const QString &instance )
+ :d(new xPLDevicePrivate)
+{
+ d->vendor = vendor;
+ d->device = device;
+ d->instance = instance;
+ d->port = 0;
+ d->heartBeatInterval = DEFAULT_HBEAT_INTERVAL;
+
+}
+
+xPLDevice::~xPLDevice() {
+ delete d;
+}
+
+QHostAddress xPLDevice::address() const {
+ return d->address;
+}
+
+int xPLDevice::heartBeatInterval() const {
+ return d->heartBeatInterval;
+}
+
+QString xPLDevice::deviceName() const {
+ return QString("%1-%2.%3").arg(d->vendor).arg(d->device).arg(d->instance);
+}
+
+QDateTime xPLDevice::lastHeartBeat() const {
+ return d->lastHeartBeat;
+}
+
+int xPLDevice::port() const {
+ return d->port;
+}
+
+void xPLDevice::setAddress( const QHostAddress &address ) {
+ d->address = address;
+}
+
+void xPLDevice::setHeartBeatInterval( int minutes ) {
+ d->heartBeatInterval = minutes;
+}
+
+void xPLDevice::setPort( int p ) {
+ d->port = p;
+}
+
+void xPLDevice::setLastHeartBeat( const QDateTime &timestamp ) {
+ d->lastHeartBeat = timestamp;
+}
View
38 xpl/qtxpl/xpldevice.h
@@ -0,0 +1,38 @@
+#ifndef XPLDEVICE_H
+#define XPLDEVICE_H
+
+#include "xplmessage.h"
+#include <QDateTime>
+#include <QHostAddress>
+
+class xPLDevicePrivate;
+
+class QTXPL_EXPORT xPLDevice
+{
+public:
+ xPLDevice( const xPLDevice & ); //Copy constructor
+ xPLDevice& operator=( xPLDevice ); //Copy assignment operator
+
+ xPLDevice( const QString &deviceName );
+ xPLDevice( const QString &vendor, const QString &device );
+ xPLDevice( const QString &vendor, const QString &device, const QString &instance );
+
+ ~xPLDevice();
+
+ QString deviceName() const;
+
+ QDateTime lastHeartBeat() const;
+
+ QHostAddress address() const;
+ int heartBeatInterval() const;
+ int port() const;
+ void setAddress( const QHostAddress &address );
+ void setHeartBeatInterval( int minutes );
+ void setPort( int port );
+ void setLastHeartBeat( const QDateTime &timestamp );
+
+private:
+ xPLDevicePrivate *d;
+};
+
+#endif // XPLDEVICE_H
View
226 xpl/qtxpl/xplinstance.cpp
@@ -0,0 +1,226 @@
+#include "xplinstance.h"
+#include "xplmessage.h"
+
+#include <QUdpSocket>
+#include <QLinkedList>
+#include <QNetworkInterface>
+
+#include <QDebug>
+#include <QTimer>
+
+class xPLInstancePrivate {
+public:
+ xPLDevice *thisDevice;
+ QLinkedList<xPLDevice> devices;
+ QUdpSocket *socket;
+ xPLInstance::OperationMode mode;
+ QHostAddress address;
+ bool isAttatched;
+ QTimer *timer;
+};
+
+xPLInstance::xPLInstance( const xPLDevice &device, QObject *parent )
+ :QObject(parent)
+{
+ d = new xPLInstancePrivate;
+ d->thisDevice = new xPLDevice(device);
+ d->mode = Disconnected;
+ d->timer = new QTimer(this);
+ this->init();
+}
+
+xPLInstance::xPLInstance( const QString &vendor, const QString &device, QObject *parent )
+ :QObject(parent)
+{
+ d = new xPLInstancePrivate;
+ d->thisDevice = new xPLDevice(vendor, device);
+ d->mode = Disconnected;
+ d->timer = new QTimer(this);
+ this->init();
+}
+
+xPLInstance::~xPLInstance() {
+ delete d->thisDevice;
+ delete d;
+}
+
+void xPLInstance::init() {
+ foreach(QHostAddress address, QNetworkInterface::allAddresses()) {
+ if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress::LocalHost) {
+ d->address = address;
+ break;
+ }
+ }
+ d->isAttatched = false;
+ d->socket = new QUdpSocket(this);
+ d->thisDevice->setPort(this->bindToPort());
+ if (d->thisDevice->port() == 0) {
+ return;
+ }
+ d->timer->setInterval( 3000 );
+ connect(d->socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
+ connect(d->timer, SIGNAL(timeout()), this, SLOT(poll()));
+ this->sendHeartbeat();
+ d->timer->start();
+}
+
+bool xPLInstance::attatched() const {
+ return this->d->isAttatched;
+}
+
+int xPLInstance::bindToPort() {
+ //Hub-mode not supported
+ /*if (d->socket->bind( XPL_PORT )) {
+ d->mode = Hub;
+ qDebug("Bind succeded as hub");
+ return XPL_PORT;
+ }*/
+ for (int port = 49152; port <= 65535; ++port) {
+ if (d->socket->bind( port, QUdpSocket::DontShareAddress )) {
+ d->mode = Client;
+ qDebug() << "Bind succeded as client on" << port;
+ return port;
+ }
+ }
+ qDebug("Bind failed");
+ return 0;
+}
+
+xPLInstance::OperationMode xPLInstance::operationMode() const {
+ return d->mode;
+}
+
+void xPLInstance::processPendingDatagrams() {
+ while (d->socket->hasPendingDatagrams()) {
+ QByteArray datagram;
+ datagram.resize(d->socket->pendingDatagramSize());
+ d->socket->readDatagram(datagram.data(), datagram.size());
+ xPLMessage *message = xPLMessage::createMessageFromString( datagram.data() );
+ if (message) {
+ processMessage( *message );
+ delete message;
+ }
+ }
+}
+
+void xPLInstance::poll() {
+ if (!attatched()) {
+ sendHeartbeat();
+ return;
+ }
+ if (d->thisDevice->lastHeartBeat().secsTo( QDateTime::currentDateTime() ) >= d->thisDevice->heartBeatInterval() * 60) {
+ sendHeartbeat();
+ }
+ //Loop all devices to see if they have timed out
+ for( QLinkedList<xPLDevice>::iterator it = d->devices.begin(); it != d->devices.end(); ) {
+ if ((*it).lastHeartBeat().secsTo( QDateTime::currentDateTime() ) >= (*it).heartBeatInterval() * 60 * 2) {
+ qDebug() << "Device removed (timeout):" << (*it).deviceName();
+ it = d->devices.erase( it );
+ continue;
+ }
+ ++it;
+ }
+}
+
+void xPLInstance::sendMessage( const xPLMessage &msg ) const {
+ xPLMessage message(msg); //Copy so we don't have const
+ message.setSource(d->thisDevice->deviceName());
+ QByteArray datagram = message.toString().toAscii();
+ d->socket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, XPL_PORT);
+}
+
+void xPLInstance::sendMessage( xPLMessage * message ) const {
+ this->sendMessage(*message);
+}
+
+void xPLInstance::sendMessage( const xPLMessage &message, const xPLDevice &device ) const {
+ QByteArray datagram = message.toString().toAscii();
+ d->socket->writeDatagram(datagram.data(), datagram.size(), device.address(), device.port());
+}
+
+void xPLInstance::processHeartBeat( const xPLMessage &message ) {
+ if (message.messageSchemeIdentifier() == "hbeat.request") {
+ sendHeartbeat();
+ return;
+ }
+ for( QLinkedList<xPLDevice>::iterator it = d->devices.begin(); it != d->devices.end(); ++it ) {
+ if ( (*it).deviceName() == message.source() ) {
+ if (message.messageSchemeIdentifier() == "hbeat.end") {
+ qDebug() << "Device removed:" << message.source();
+ d->devices.erase( it );
+ return;
+ } else {
+ (*it).setLastHeartBeat( QDateTime::currentDateTime() );
+ (*it).setHeartBeatInterval( message.bodyItem( "interval" ).toInt() );
+ }
+ return;
+ }
+ }
+ if (!message.messageSchemeIdentifier().endsWith("app") && !message.messageSchemeIdentifier().endsWith("basic")) {
+ return;
+ }
+ qDebug() << "New device:" << message.source();
+ xPLDevice device( message.source() );
+ device.setHeartBeatInterval( message.bodyItem("interval").toInt() );
+ device.setLastHeartBeat( QDateTime::currentDateTime() );
+ if (message.messageSchemeIdentifier() == "hbeat.app") {
+ device.setAddress( QHostAddress(message.bodyItem("remote-ip")) );
+ device.setPort( message.bodyItem("port").toInt() );
+ }
+ d->devices.append( device );
+}
+
+void xPLInstance::processMessage( const xPLMessage &message ) {
+ if (!attatched() && message.messageSchemeIdentifier() == "hbeat.app" && message.source() == d->thisDevice->deviceName()) {
+ //Our own echo
+ setAttatched( true );
+ return;
+ }
+ if (message.source() == d->thisDevice->deviceName()) {
+ //Ignore messages from ourselves
+ return;
+ }
+ if (message.messageSchemeIdentifier().startsWith("hbeat") || message.messageSchemeIdentifier().startsWith("config")) {
+ processHeartBeat( message );
+ }
+ if (d->mode == xPLInstance::Hub) {
+ //Reply the message to all clients
+ for( QLinkedList<xPLDevice>::iterator it = d->devices.begin(); it != d->devices.end(); ++it ) {
+ sendMessage(message, *it);
+ }
+ }
+ if (message.target() != d->thisDevice->deviceName() && message.target() != "*") {
+ //Message not for us
+ return;
+ }
+ xPLMessage newMsg(message);
+ emit messageReceived(&newMsg);
+}
+
+void xPLInstance::sendHeartbeat() {
+ xPLMessage message( xPLMessage::xplstat );
+ message.setMessageSchemeIdentifier( "hbeat.app" );
+ message.setTarget("*");
+ message.setSource( d->thisDevice->deviceName() );
+ message.addBodyItem( "interval", QString::number(d->thisDevice->heartBeatInterval()) );
+ message.addBodyItem( "port", QString::number(d->thisDevice->port()) );
+ message.addBodyItem( "remote-ip", d->address.toString() );
+ sendMessage( message );
+ d->thisDevice->setLastHeartBeat( QDateTime::currentDateTime() );
+}
+
+void xPLInstance::setAttatched( bool attatched ) {
+ d->isAttatched = attatched;
+ if (d->isAttatched) {
+ qDebug() << "Attached to network!";
+ d->timer->setInterval( 60000 ); //Once a minute
+
+ xPLMessage message( xPLMessage::xplcmnd );
+ message.setTarget( "*" );
+ message.setSource( d->thisDevice->deviceName() );
+ message.setMessageSchemeIdentifier( "hbeat.request" );
+ message.addBodyItem("command", "request");
+ sendMessage( message );
+ emit attachedToNetwork();
+ }
+}
View
55 xpl/qtxpl/xplinstance.h
@@ -0,0 +1,55 @@
+#ifndef XPLINSTANCE_H
+#define XPLINSTANCE_H
+
+#include <QObject>
+#include "xpldevice.h"
+#include "xplmessage.h"
+
+const int XPL_PORT = 3865;
+
+class QTimer;
+class xPLInstancePrivate;
+
+class QTXPL_EXPORT xPLInstance : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS( OperationMode );
+
+ Q_PROPERTY( OperationMode operationMode READ operationMode );
+public:
+ enum OperationMode { Client, Disconnected, Hub };
+
+ xPLInstance( const xPLDevice &device, QObject *parent = 0 );
+ xPLInstance( const QString &vendor, const QString &device, QObject *parent = 0 );
+ ~xPLInstance();
+
+public slots:
+ bool attatched() const;
+
+ OperationMode operationMode() const;
+
+ void sendMessage( const xPLMessage &message ) const;
+ void sendMessage( xPLMessage * message ) const;
+ void sendMessage( const xPLMessage &message, const xPLDevice &device ) const;
+
+signals:
+ void messageReceived(xPLMessage *message);
+ void attachedToNetwork();
+
+private slots:
+ void processPendingDatagrams();
+ void sendHeartbeat();
+ void poll();
+
+private:
+ void processHeartBeat( const xPLMessage &message );
+ void processMessage( const xPLMessage &message );
+ void init();
+ int bindToPort();
+ void setAttatched( bool attatched );
+
+ xPLInstancePrivate *d;
+};
+
+#endif // XPLINSTANCE_H
View
188 xpl/qtxpl/xplmessage.cpp
@@ -0,0 +1,188 @@
+#include "xplmessage.h"
+
+#include <QStringList>
+#include <QMap>
+#include <QDebug>
+
+class xPLMessage::xPLMessagePrivate {
+public:
+ xPLMessage::Identifier identifier;
+ int hop;
+ QString source, target, msi;
+ QMap<QString, QString> headExtra, body;
+};
+
+xPLMessage::xPLMessage( const xPLMessage &other )
+ : QObject(),
+ d( new xPLMessagePrivate( *other.d ))
+{
+ //do nothing
+}
+
+xPLMessage& xPLMessage::operator=( xPLMessage other ) {
+ std::swap( this->d, other.d );
+ return *this;
+}
+
+
+xPLMessage::xPLMessage(Identifier i)
+ :QObject(),
+ d(new xPLMessagePrivate)
+{
+ d->hop = 1;
+ d->identifier = i;
+ d->target = "*";
+}
+
+xPLMessage::xPLMessage()
+ :QObject(),
+ d(new xPLMessagePrivate)
+{
+
+ d->hop = 1;
+ d->identifier = xplcmnd;
+ d->target = "*";
+}
+
+xPLMessage::~xPLMessage() {
+ delete d;
+}
+
+
+void xPLMessage::addBodyItem( const QString &key, const QString &value ) {
+ d->body[key] = value;
+}
+
+void xPLMessage::addHeadItem( const QString &key, const QString &value ) {
+ if (key == "hop") {
+ d->hop = value.toInt();
+ } else if (key == "source") {
+ setSource(value);
+ } else if (key == "target") {
+ setTarget(value);
+ } else {
+ d->headExtra[key] = value;
+ }
+}
+
+QString xPLMessage::bodyItem( const QString &key ) const {
+ if (d->body.contains(key)) {
+ return d->body[key];
+ }
+ return "";
+}
+
+QString xPLMessage::headItem( const QString &key ) const {
+ if (d->headExtra.contains(key)) {
+ return d->headExtra[key];
+ }
+ return "";
+}
+
+QString xPLMessage::messageSchemeIdentifier() const {
+ return d->msi;
+}
+
+QString xPLMessage::source() const {
+ return d->source;
+}
+
+QString xPLMessage::target() const {
+ return d->target;
+}
+
+void xPLMessage::setMessageSchemeIdentifier( const QString &messageSchemeIdentifier ) {
+ d->msi = messageSchemeIdentifier;
+}
+
+void xPLMessage::setSource( const QString &value ) {
+ d->source = value;
+}
+
+void xPLMessage::setTarget( const QString &value ) {
+ d->target = value;
+}
+
+QString xPLMessage::toString() const {
+ QString message;
+
+ switch( d->identifier ) {
+ case xplcmnd:
+ message += "xpl-cmnd\n";
+ break;
+ case xplstat:
+ message += "xpl-stat\n";
+ break;
+ case xpltrig:
+ message += "xpl-trig\n";
+ break;
+ default:
+ return "";
+ }
+
+ message += "{\n";
+ message += QString("hop=%1\n").arg(d->hop);
+ message += QString("source=%1\n").arg(d->source);
+ message += QString("target=%1\n").arg(d->target);
+ for( QMap<QString, QString>::const_iterator it = d->headExtra.begin(); it != d->headExtra.end(); ++it ) {
+ message += QString("%1=%2\n").arg(it.key()).arg(it.value());
+ }
+ message += "}\n";
+ message += d->msi + "\n";
+ message += "{\n";
+ for( QMap<QString, QString>::const_iterator it = d->body.begin(); it != d->body.end(); ++it ) {
+ message += QString("%1=%2\n").arg(it.key()).arg(it.value());
+ }
+ message += "}\n";
+
+ return message;
+}
+
+xPLMessage *xPLMessage::createMessageFromString( const QString &message ) {
+ QStringList lines = message.split('\n', QString::SkipEmptyParts);
+ QStringList::const_iterator it = lines.begin();
+
+ Identifier i;
+
+ if (*it == "xpl-cmnd") {
+ i = xplcmnd;
+ } else if (*it == "xpl-stat") {
+ i = xplstat;
+ } else if (*it == "xpl-trig") {
+ i = xpltrig;
+ } else {
+ return 0;
+ }
+ ++it;
+
+ if (*it != "{") {
+ return 0;
+ }
+ ++it;
+
+ xPLMessage *msg = new xPLMessage(i);
+ for(; it != lines.end() && *it != "}"; ++it) {
+ msg->addHeadItem( (*it).section('=', 0, 0), (*it).section('=', 1) );
+ }
+ if (it == lines.end()) {
+ delete msg;
+ return 0;
+ }
+ ++it;
+
+ msg->setMessageSchemeIdentifier( *it );
+ ++it;
+
+ if (*it != "{") {
+ delete msg;
+ return 0;
+ }
+ ++it;
+
+ for(; it != lines.end() && *it != "}"; ++it) {
+ msg->addBodyItem( (*it).section('=', 0, 0), (*it).section('=', 1) );
+ }
+
+ return msg;
+}
+
View
57 xpl/qtxpl/xplmessage.h
@@ -0,0 +1,57 @@
+#ifndef XPLMESSAGE_H
+#define XPLMESSAGE_H
+
+#ifdef _WINDOWS
+ #ifdef qtxpl_EXPORTS
+ #define QTXPL_EXPORT __declspec(dllexport)
+ #else
+ #define QTXPL_EXPORT __declspec(dllimport)
+ #endif
+#else
+ #define QTXPL_EXPORT
+#endif
+
+#include <QObject>
+#include <QMetaType>
+
+class QTXPL_EXPORT xPLMessage : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS( Identifier );
+public:
+ enum Identifier { xplcmnd, xplstat, xpltrig };
+
+ xPLMessage( const xPLMessage & ); //Copy constructor
+ xPLMessage& operator=( xPLMessage ); //Copy assignment operator
+
+ xPLMessage(Identifier identifier);
+ xPLMessage();
+ virtual ~xPLMessage();
+
+ static xPLMessage *createMessageFromString( const QString &message );
+
+public slots:
+ void addBodyItem( const QString &key, const QString &value );
+ void addHeadItem( const QString &key, const QString &value );
+
+ QString bodyItem( const QString &key ) const;
+ QString headItem( const QString &key ) const;
+ QString messageSchemeIdentifier() const;
+ QString source() const;
+ QString target() const;
+
+ void setMessageSchemeIdentifier( const QString &msi );
+ void setSource( const QString &value );
+ void setTarget( const QString &value );
+
+ QString toString() const;
+
+private:
+ class xPLMessagePrivate;
+ xPLMessagePrivate *d;
+};
+
+Q_DECLARE_METATYPE(xPLMessage*)
+
+#endif // XPLMESSAGE_H
View
37 xpl/telldus-core-xpl/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for xPLLib
+#
+
+#
+# For LINUX, use the following
+CCOPTS = -g -DLINUX -pedantic -Wall
+LIBS = -g -lm -lxPL -ltelldus-core
+
+LDOPTS = -O
+CC = cc $(CCOPTS)
+LD = cc $(LDOPTS)
+
+CMD_LIST = xPL_TelldusCore
+
+.c.o:
+ $(CC) -c $<
+
+.o:
+ $(LD) -o $@ $< $(LIBS)
+
+.c:
+ $(CC) -c $<
+ $(LD) -o $@ $< $(LIBS)
+
+
+all: ${CMD_LIST}
+
+clean:
+ rm -f *.o *.a core ${CMD_LIST}
+
+rebuild: clean all
+
+
+
+
+
View
399 xpl/telldus-core-xpl/xPL_TelldusCore.c
@@ -0,0 +1,399 @@
+
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <math.h>
+#include <xPL.h>
+#include <telldus-core.h>
+
+#define TELLDUS_VERSION "1.0"
+#define INSTANCE_MAX 16
+
+static xPL_ServicePtr telldusService = NULL;
+static Bool daemonMode = TRUE;
+char hostname[INSTANCE_MAX];
+
+void sendDevInfo(xPL_MessagePtr msg);
+void sendDevList(xPL_MessagePtr msg);
+void sendGatewayInfo();
+void sendNetInfo(xPL_MessagePtr msg);
+void sendNetList();
+
+void lightingCommandHandler(xPL_ServicePtr theService, xPL_MessagePtr theMessage, xPL_ObjectPtr userValue) {
+ Bool found = FALSE;
+ int deviceCount = 0, deviceId = 0, i, level = 0;
+
+ if (!xPL_doesMessageNamedValueExist(theMessage, "command")) {
+ return;
+ } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "command"), "goto") != 0) {
+ return;
+ }
+
+ if (!xPL_doesMessageNamedValueExist(theMessage, "network")) {
+ return;
+ } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "network"), "1") != 0) {
+ return;
+ }
+
+ if (!xPL_doesMessageNamedValueExist(theMessage, "device")) {
+ return;
+ } else {
+ /* Loop the devices to see it realy exists */
+ deviceCount = tdGetNumberOfDevices();
+
+ xPL_strToInt(xPL_getMessageNamedValue(theMessage, "device"), &deviceId);
+ for( i = 0; i < deviceCount; ++i ) {
+ if (tdGetDeviceId(i) == deviceId) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found == FALSE) {
+ return;
+ }
+ }
+
+ if (!xPL_doesMessageNamedValueExist(theMessage, "level")) {
+ return;
+ } else {
+ xPL_strToInt(xPL_getMessageNamedValue(theMessage, "level"), &level);
+ if (level < 0 || level > 100) {
+ return;
+ }
+ level = (float)level * 255.0 / 100.0;
+ }
+
+ if (level > 0 && level < 255) {
+ /* See if the device supports dim */
+ if (!(tdMethods(deviceId, TELLSTICK_DIM) & TELLSTICK_DIM)) {
+ /* Non dimmable device was dimmed */
+ return;
+ }
+ tdDim(deviceId, (unsigned char)level);
+ } else if (level == 255) {
+ /* See if the device supports dim */
+ if (!(tdMethods(deviceId, TELLSTICK_TURNON) & TELLSTICK_TURNON)) {
+ /* Non dimmable device was dimmed */
+ return;
+ }
+ tdTurnOn(deviceId);
+ } else if (level == 0) {
+ /* See if the device supports dim */
+ if (!(tdMethods(deviceId, TELLSTICK_TURNOFF) & TELLSTICK_TURNOFF)) {
+ /* Non dimmable device was dimmed */
+ return;
+ }
+ tdTurnOff(deviceId);
+ }
+
+}
+
+void lightingRequestHandler(xPL_ServicePtr theService, xPL_MessagePtr theMessage, xPL_ObjectPtr userValue) {
+
+ if (!xPL_doesMessageNamedValueExist(theMessage, "request")) {
+ return;
+ }
+
+ if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "devinfo") == 0) {
+ sendDevInfo(theMessage);
+ } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "devlist") == 0) {
+ sendDevList(theMessage);
+ } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "gateinfo") == 0) {
+ sendGatewayInfo();
+ } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "netinfo") == 0) {
+ sendNetInfo(theMessage);
+ } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "netlist") == 0) {
+ sendNetList();
+ } else {
+/* fprintf(stdout, "Request: %s\n", xPL_getMessageNamedValue(theMessage, "request")); */
+ }
+}
+
+void shutdownHandler(int onSignal) {
+ xPL_setServiceEnabled(telldusService, FALSE);
+ xPL_releaseService(telldusService);
+ xPL_shutdown();
+ exit(0);
+}
+
+void sendDevInfo(xPL_MessagePtr msg) {
+ xPL_MessagePtr message = NULL;
+ Bool found = FALSE, deviceCount = tdGetNumberOfDevices();
+ int deviceId = 0, methods = 0, i = 0, lastSentCommand, level = 0;
+ char *name, buffer[12], *value;
+
+ xPL_strToInt(xPL_getMessageNamedValue(msg, "device"), &deviceId);
+ for( i = 0; i < deviceCount; ++i ) {
+ if (tdGetDeviceId(i) == deviceId) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ message = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_STATUS);
+ xPL_setSchema(message, "lighting", "devinfo");
+
+ xPL_setMessageNamedValue(message, "network", xPL_getMessageNamedValue(msg, "network"));
+ xPL_setMessageNamedValue(message, "device", xPL_getMessageNamedValue(msg, "device"));