Changes between Version 41 and Version 42 of Proposal


Ignore:
Timestamp:
Jul 8, 2013, 1:51:19 PM (11 years ago)
Author:
Frédéric
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Proposal

    v41 v42  
    3434{{{
    3535#!python
    36 from pknyx.api import FunctionalBlock, Stack, ETS
     36from pknyx.api import FunctionalBlock, Stack, ETS, Scheduler
     37
     38
     39stack = Stack(individualAddress="1.2.3")
     40ets = ETS(stack)
     41schedule = Scheduler()
    3742
    3843
     
    4550    GO_02 = dict(dp="humidity", flags="CRT", priority="low")
    4651
    47 
    48 weatherTempBlock = WeatherTemperatureBlock(name="weather_tempertature", desc="A simple weather block example")
    49 
    50 stack = Stack(individualAddress="1.2.3")
    51 ets = ETS(stack)
    52 
    53 ets.weave(fb=weatherTempBlock, dp="temperature", gad="1/1/1")
    54 ets.weave(fb=weatherTempBlock, dp="humidity", gad="1/1/2")
    55 
    56 stack.run()
    57 }}}
    58 
    59 That's it! As you can see, concepts used here are simple... This Functional Block can be then used from any other real device of your installation, through Groups Addresses {{{1/1/1}}} and {{{1/1/2}}}. All you have to do, is to weave (link, bind...) the Group Objects of your real devices to these Groups Addresses, using the real '''ETS''' application.
    60 
    61 Lets have a closer look to this example. First, we import some python objects:
    62 
    63 {{{
    64 #!python
    65 from pknyx.api import FunctionalBlock, Stack, ETS
    66 }}}
    67 
    68 These objects are classes.
    69 
    70 Then, we create a custom Functional Block; this is done by subclassing the '''!FunctionBlock''' base class, and adding a few attributes:
    71 
    72 {{{
    73 #!python
    74 class WeatherTemperatureBlock(FunctionalBlock):
    75 
    76     DP_01 = dict(name="temperature", access="output", dptId="9.001", default=19.)
    77     DP_02 = dict(name="humidity", access="output", dptId="9.007", default=50.)
    78 
    79     GO_01 = dict(dp="temperature", flags="CRT", priority="low")
    80     GO_02 = dict(dp="humidity", flags="CRT", priority="low")
    81 }}}
    82 
    83 The {{{DP_xx}}} class attributes are the Datapoints of our Functional Block. The {{{GO_xx}}} class attributes are the Group Objects mapping the Datapoints to the bus. They are both defined as python dictionnary; they will be automatically instanciated for you by the framework. The named used here does not matter, as long as they start with {{{DP_}}} for Datapoints, and {{{GO_}}} for Group Objects.
    84 
    85 Then, we just instanciate our new Funtional Block:
    86 
    87 {{{
    88 #!python
    89 weatherTempBlock = WeatherTemperatureBlock(name="weather_tempertature", desc="A simple weather block example")
    90 }}}
    91 
    92 We also need to instanciante some global high level objects:
    93 
    94 {{{
    95 #!python
    96 stack = Stack(individualAddress="1.2.3")
    97 ets = ETS(stack)
    98 }}}
    99 
    100 The {{{Stack}}} object is used to communicate over the bus (real bus, of course, but also on virtual bus). We can give it an Individual Address, to mimic real devices behaviour.
    101 
    102 The {{{ETS}}} object is a tool which works like the reall ETS application, and used to weave (bind, link...) our Group Objects to Group Addresses:
    103 
    104 {{{
    105 #!python
    106 ets.weave(fb=weatherTempBlock, dp="temperature", gad="1/1/1")
    107 ets.weave(fb=weatherTempBlock, dp="humidity", gad="1/1/2")
    108 }}}
    109 
    110 And finally:
    111 
    112 {{{
    113 #!python
    114 stack.serve()
    115 }}}
    116 
    117 This call is blocking, and launch the framework main loop.
    118 
    119 We now have a process (Device) running, listening to the bus. The Datapoints, through their respective Group Objects, will react to requests on the Group Addresses their are weaved to ("1/1/1" and "1/1/2"). According to the flags, they will transmit their internal value on a Read request, or if this value changes.
    120 
    121 Ok, but our Functional Block is not really usefull yet, as it does not refresh its Datapoints! Let's see how it can be done:
    122 
    123 {{{
    124 #!python
    125 from pknyx.api import FunctionalBlock, Stack, ETS
    126 from pknyx.api import Scheduler
    127 
    128 
    129 schedule = Scheduler()
    130 
    131 
    132 class WeatherTemperatureBlock(FunctionalBlock):
    133 
    134     DP_01 = dict(name="temperature", access="output", dptId="9.001", default=19.)
    135     DP_02 = dict(name="humidity", access="output", dptId="9.007", default=50.)
    136 
    137     GO_01 = dict(dp="temperature", flags="CRT", priority="low")
    138     GO_02 = dict(dp="humidity", flags="CRT", priority="low")
    139 
    14052    @schedule.every(minute=5)
    141     def updateTemperaturHumidity(self, event):
    142 
    143         # How we retreive the temperature/humidity is out of the scope of this proposal
     53    def updateTemperatureHumidity(self, event):
    14454        # temperature = xxx
    14555        # humidity = xxx
     
    15060weatherTempBlock = WeatherTemperatureBlock(name="weather_tempertature", desc="A simple weather block example")
    15161
     62ets.weave(fb=weatherTempBlock, dp="temperature", gad="1/1/1")
     63ets.weave(fb=weatherTempBlock, dp="humidity", gad="1/1/2")
     64
     65stack.run()
     66}}}
     67
     68That's it! As you can see, concepts used here are simple... This Functional Block can be then used from any other real device of your installation, through Groups Addresses {{{1/1/1}}} and {{{1/1/2}}}. All you have to do, is to weave (link, bind...) the Group Objects of your real devices to these Groups Addresses, using the real '''ETS''' application.
     69
     70Lets have a closer look to this example. First, we import some python objects:
     71
     72{{{
     73#!python
     74from pknyx.api import FunctionalBlock, Stack, ETS,  Scheduler
     75}}}
     76
     77These objects are classes.
     78
     79We then instanciante some high level objects and helpers:
     80
     81{{{
     82#!python
    15283stack = Stack(individualAddress="1.2.3")
    15384ets = ETS(stack)
    154 
    155 ets.weave(fb=weatherTempBlock, dp="temperature", gad="1/1/1")
    156 ets.weave(fb=weatherTempBlock, dp="humidity", gad="1/1/2")
    157 
    158 stack.run()
    159 }}}
    160 
    161 We have just imported and instanciated an additionnal object:
    162 
    163 {{{
    164 #!python
    165 from pknyx.api import Scheduler
    166 
    167 
    16885schedule = Scheduler()
    16986}}}
    17087
    171 We have also defined a method which role is to update the temperature and humidity Datapoints values:
     88The {{{Stack}}} object is used to communicate over the bus (real bus, of course, but also virtual bus). We can give it an Individual Address, to mimic real devices behaviour. This address will be used as Source Address when communicating over the bus.
     89
     90The {{{ETS}}} object is a tool which works more or less like the real ETS application (see below).
     91
     92The {{{Scheduler}}} is a helper implementating a powerfull scheduler (see below).
     93
     94The main part is to create our custom Functional Block; this is done by subclassing the '''!FunctionBlock''' base class, and adding a few attributes/methods:
     95
     96{{{
     97#!python
     98class WeatherTemperatureBlock(FunctionalBlock):
     99
     100    DP_01 = dict(name="temperature", access="output", dptId="9.001", default=19.)
     101    DP_02 = dict(name="humidity", access="output", dptId="9.007", default=50.)
     102
     103    GO_01 = dict(dp="temperature", flags="CRT", priority="low")
     104    GO_02 = dict(dp="humidity", flags="CRT", priority="low")
     105}}}
     106
     107The {{{DP_xx}}} class attributes are the Datapoints of our Functional Block. The {{{GO_xx}}} class attributes are the Group Objects mapping the Datapoints to the bus. They are both defined as python dictionnary; they will be automatically instanciated for us by the framework. The named used here do not matter, as long as they start with {{{DP_}}} for Datapoints, and {{{GO_}}} for Group Objects.
     108
     109There are a few parameters in the dicts; some are obvious, some will need more explanations. But this is out of the scope of this proposal.
     110
     111In our class, we also defined a method which role is to update the temperature and humidity Datapoints values:
    172112
    173113{{{
    174114#!python
    175115    @schedule.every(minute=5)
    176     def updateTemperaturHumidity(self, event):
    177 
    178         # How we retreive the temperature/humidity is out of the scope of this proposal
     116    def updateTemperatureHumidity(self, event):
    179117        # temperature = xxx
    180118        # humidity = xxx
     
    185123Note how this method is periodically called, using the {{{schedule.every()}}} method as python decorator. This decorator will automatically register our method and call it every 5 minutes.
    186124
    187 In our method, we retreive the temperature and humidity values (not explained here), and give the value to the respective Datapoints. If the value has changed from the previous call, the Datapoint will automagically transmit it to the bus (according to the flags, of course).
     125In this method, we get the temperature and humidity values (not explained here), and give the value to the respective Datapoints.
     126
     127Then, we instanciate our new Funtional Block:
     128
     129{{{
     130#!python
     131weatherTempBlock = WeatherTemperatureBlock(name="weather_tempertature", desc="A simple weather block example")
     132}}}
     133
     134and use the {{{ETS}}} object to weave (bind, link...) our Datapoints (their matching Group Objects, in fact) to Group Addresses:
     135
     136{{{
     137#!python
     138ets.weave(fb=weatherTempBlock, dp="temperature", gad="1/1/1")
     139ets.weave(fb=weatherTempBlock, dp="humidity", gad="1/1/2")
     140}}}
     141
     142And finally, we launch the framework main loop:
     143
     144{{{
     145#!python
     146stack.serve()
     147}}}
     148
     149(this call is blocking).
     150
     151We now have a process (Device) running, listening to the bus. The Datapoints, through their respective Group Objects, will react to requests on the Group Addresses they are weaved to ("1/1/1" and "1/1/2"). According to the flags, they will transmit their internal value on Read requests or if their value internally change (updated). Yes, you don't have to manage this: '''pKNyX''' does it for you! This is the all point of a framework, isn't it?
    188152
    189153That's it for now. This is only a draft version; final implementation may change, according to feedback/suggestions I will get. But the core is all there. Again, the goal of the framework is to provide very high level tools to build complete and powerfull applications and KNX extensions.