1
using namespace dss;
2
3
/**
4
\mainpage digitalStrom Server
5
6
\image html digitalSTROM_small.png
7
8
\section overview Overview
9
10
The dSS consists of several subsystems as shown in the following image:
11
12
\image html block.png "System overview"
13
\image latex block.eps "System overview" height=10cm
14
15
Every subsystem can be enabled or disabled by the commandline or in the configuration.
16
The center piece of the dSS is its DataModel. It provides the API that allows a developer manipulate as well as rearrange devices, zones and groups.
17
Built on that foundation there is a SOAP interface to make the API accessible to the outside world. In addition to the SOAP interface there is a JSON interface that interacts with JavaScript running in a webbrowser.
18
19
The DS485Proxy is responsible of controlling the physical and simulated devices. It converts abstract commands from the DataModel an converts them to one or several DS485 frames. These frames will then be sent either to a simulated dSM or put on the wire depending on the frame's destination.
20
21
The simulated dSM may be extended by plugins. An example is a simulated dSID that controlls a VLC (mediaplayer) instance remotely using its telnet interface.
22
23
\section config Configuration
24
25
There are several configuration files which define the behaviour of the dSS and its simulation. Most of the things can be manipulated at runtime through the property system.
26
27
\section properties Property system
28
29
The property system is a tree based configuration and information tool. It is populated by the subsystems at startup. The whole system is accessible at http://yourdss:8080/browse/. Properties can be specified on the command-line like that:
30
\verbatim
31
dss --prop:/path/to/property=value
32
\endverbatim
33
34
\subsection config_general General
35
36
The main config file is located at data/config.xml. It will get loaded on
37
startup and patched into the property system.
38
39
\verbatim
40
<?xml version="1.0" encoding="utf-8"?>
41
<?xml version="1.0" encoding="utf-8"?>
42
<properties version="1">
43
  <property name="config">
44
    <property name="subsystems/DS485Proxy/rs485devicename" type="string">
45
      <value>/dev/ttyUSB0</value>
46
    </property>
47
    <property name="subsystems/Webserver/webroot" type="string">
48
      <value>/mnt/sdcard/webroot</value>
49
    </property>
50
    <property name="subsystems/Metering/enabled" type="boolean">
51
      <value>false</value>
52
    </property>
53
  </property>
54
</properties>
55
\endverbatim
56
57
Each subsystem has an entry in the config subtree with at least two entries \c loglevel and \c enabled. If a subsystem is not enabled it won't get started. The loglevel (0 - 5) defines the verbosity with 0 being the most verbose.
58
59
\subsection config_apartment Apartment
60
61
The Apartment config resides in data/apartment.xml. It contains everything that won't be stored in the dSMs such as device names that are longer than 20 characters.
62
63
\verbatim
64
<?xml version='1.0' encoding='utf-8'?>
65
<config version="1">
66
  <apartment>
67
    <name>Sim Residence</name>
68
  </apartment>
69
  <devices>
70
    <device dsid="3504175fe0000000ffc00011">
71
      <name>Bulb 1</name>
72
      <location>
73
        <x>1.1</x>
74
        <y>2.5</y>
75
        <z>0</z>
76
      </location>
77
    </device>
78
    <device dsid="3504175fe0000000ffc00006">
79
      <name>Bell</name>
80
      <location>
81
        [...]
82
      </location>
83
    </device>
84
  </devices>
85
  <zones>
86
    <zone id="1">
87
      <name>Zone 1</name>
88
    </zone>
89
    [...]
90
  </zones>
91
</config>
92
\endverbatim
93
94
All items are bound to a dsid so if a user moves a bulb from one zone to another it will still be named "Bulb 1". Note that this file will be generated by the dSS each time a name or location changes.
95
96
\subsection config_sim Simulation
97
98
The simulation has it's own configuration:
99
100
\verbatim
101
<?xml version="1.0"?>
102
<sim>
103
  <dsMeter busid="70" dsid="10">
104
    <zone id="1"> <!-- id can be omitted, in fact zone may be omitted if there's only one zone -->
105
      <device dsid="1" busid="1" type="standard.switch" />
106
      <device dsid="2" busid="2" type="example.vlc_remote" />
107
      <device dsid="4" busid="4" type="standard.simple"/>
108
      <group id="1">
109
        <device busid="4" />
110
      </group>
111
      <group id="4">
112
        <device busid="2" />
113
      </group>
114
    </zone>
115
    <zone id="2">
116
      <device dsid="3" busid="3" type="standard.switch"/>
117
      <device dsid="5" busid="5" type="standard.simple" />
118
      <group id="1">
119
        <device busid="5" />
120
      </group>
121
    </zone>
122
  </dsMeter>
123
  <dsMeter ...>
124
  </dsMeter>
125
</sim>
126
\endverbatim
127
128
The \c sim tag encloses multiple dsMeters. In the \c dsMeter tag the dsMeters busid (as in DS485 bus address) as well as its dsid get specified. The dsid as it's written there is actually expanded in the loader to be a "simulation" address and thus prefixed with 3504175fe0000000ffc. This applies for all dsids in this config file.
129
130
The device-type defines what object gets instanciated by the simulated dSM. There are two built-in dSIDs "standard.simple" a device that behaves like a light bulb and "standard.switch" which simulates a 9 button switch.
131
If the type of a device is not specified it defaults to "standard.simple".
132
133
It's possible to write custom dSIDs with the use of the plugin API. The standard location of the plugins is at "data/plugins". For each file there a couple of checks (such as comparing the API version) are performed to ensure the stability of the dSS. The plugin is then asked for it's name and registered in the plugin factory, ready to use.
134
135
To form groups inside a zone a group tag containing references to the devices must be inserted. At the moment it's not possible to define devices inside a group tag.
136
137
\section compiling Compiling
138
139
This section should give some hints about compiling the dSS.
140
141
\subsection prerequisites Prerequisites
142
143
The following libraries and their development headers have to be present on the system:
144
145
\li libxml
146
\li boost
147
\li poco
148
\li gsoap
149
\li libical
150
\li spidermonkey
151
152
\subsection building Building
153
154
Building should be as easy as:
155
156
\verbatim
157
cd dss/build
158
cmake ..
159
make
160
\endverbatim
161
162
There are several compile time options that can be passed to cmake:
163
164
\li \c -DWITH_DATADIR=path specifies the default location of the data directory.
165
\li \c -DWITH_TESTS=[yes|no] include tests in the build.
166
\li \c -DCMAKE_BUILD_TYPE=[Release|Debug]
167
168
If you're creating backtraces for error reporting, please use \c -DCMAKE_BUILD_TYPE=Debug.
169
170
\section sets Sets
171
172
The following section will show the use of the dSS Model API. One of the most important element of the API is the Set.
173
174
Every \a dss::deviceContainer can deliver its \a dss::devices as a \a dss::set. A Set can be manipulated by adding and removing devices as well as being combined with other sets. Since a Set implements \a dss::iDeviceInterface it can receive commands like TurnOn() as it would be a single Device.
175
176
\subsection working_with_sets Working with sets
177
178
\code
179
Apartment apt;
180
181
Device& dev1 = apt.allocateDevice(1);
182
Device& dev2 = apt.allocateDevice(2);
183
Device& dev3 = apt.allocateDevice(3);
184
Device& dev4 = apt.allocateDevice(4);
185
186
// Get a set containing all devices
187
Set allDevices = apt.getDevices();
188
189
// Create a set containing only dev1
190
Set setdev1 = Set(dev1);
191
192
// Create a set of all devices excluding dev1
193
Set allMinusDev1 = allDevices.remove(setdev1);
194
195
// Create a set of all device by combining the sets created above
196
Set allRecombined = allMinusDev1.combine(setdev1);
197
198
// Turn on all devices
199
allRecombined.turnOn();
200
201
// Turn on all lights
202
Set allLights = allDevices.getByGroup("yellow");
203
allLights.turnOn();
204
205
\endcode
206
207
\section websites Default websites
208
209
All websites present on the dSS reside in \c data/webroot. They may be viewed by pointing a browser to http://localhost:8080/. To create zones or regroup devices there is a very basic interface at \c http://localhost:8080/structure.html. The server-port is announced over mDNS (Bonjour) using the service name \c _dssweb._tcp.
210
211
\section plugins Simulation plugins
212
213
Each plugin has to meet a certain API. This API is located at "core/sim/include/dsid_plugin.h". Each function has to be present in order to function correctly.
214
215
The first function to be called is:
216
217
\code
218
  int dsid_getversion();
219
\endcode
220
221
It has to return DSID_PLUGIN_API_VERSION as defined in dsid_plugin.h. This number will change with each major API change.
222
One of the next calls is to:
223
\code
224
  const char* dsid_get_plugin_name();
225
\endcode
226
227
This call should return a pointer to the plugins name. It has to be unique on the system. The prefered naming scheme is company.product if a plugin simulates the behaviour of a specific device.
228
229
If the plugin name comes up in sim.xml an instance of the plugin is created by calling:
230
\code
231
  int dsid_create_instance();
232
\endcode
233
234
The result of dsid_create_instance is a handle that identifies the newly created instance. This is done to allow multiple instances of a simulated dSID.
235
236
After allocating an the dSS needs a way to talk to the instance. This is done through a structure wich contains several function pointers. This structure is returned by:
237
\code
238
  struct dsid_interface* dsid_get_interface();
239
\endcode
240
241
The structure looks like that:
242
\code
243
  struct dsid_interface {
244
    double (*get_value)(int _handle, int _parameterNumber);
245
    void (*set_value)(int _handle, int _parameterNumber, double _value);
246
    void (*increase_value)(int _handle, int _parameterNumber);
247
    void (*decrease_value)(int _handle, int _parameterNumber);
248
    void (*call_scene)(int _handle, int _sceneNr);
249
    void (*save_scene)(int _handle, int _sceneNr);
250
    void (*undo_scene)(int _handle, int _sceneNr);
251
    void (*enable)(int _handle);
252
    void (*disable)(int _handle);
253
    void (*get_group)(int _handle);
254
255
    void (*start_dim)(int _handle, int _directionUp, int _parameterNumber);
256
    void (*end_dim)(int _handle, int _parameterNumber);
257
    int (*get_group_id)(int _handle);
258
    int (*get_function_id)(int _handle);
259
260
    const char* (*get_parameter_name)(int _handle, int _parameterNumber);
261
262
    void (*set_configuration_parameter)(int _handle, const char* _name, const char* _value);
263
    int (*get_configuration_parameter)(int _handle, const char* _name, char* _value, int _maxLen);
264
  };
265
\endcode
266
267
The first parameter to each function is the instance identifier or handle to the instance.
268
269
The plugin has to be compiled as a shared-object. Here is an example of a makefile:
270
271
\verbatim
272
all:    vlc_remote.so install
273
274
vlc_remote.so2: vlc_remote.o
275
        #g++ -lPocoNet -lpthread -shared -Wl,-soname,vlc_remote.so -o vlc_remote.so *.o
276
        g++ -shared -o vlc_remote.so *.o
277
278
279
vlc_remote.so:  vlc_remote.cpp ../../../core/sim/plugin/pluginbase.cpp ../../../core/sim/plugin/pluginmedia.cpp ../../../core/sim/include/dsid_plugin.h
280
                g++ -g3 -O0 -Wall -fPIC -shared vlc_remote.cpp ../../../core/sim/plugin/pluginbase.cpp ../../../core/sim/plugin/pluginmedia.cpp -o vlc_remote.so
281
282
install:        vlc_remote.so
283
        cp vlc_remote.so ../../../data/plugins/
284
\endverbatim
285
286
Ensure that -fPIC is present, else it won't generate position independent code and is thus unsuitable for a shared-object.
287
288
\subsection plugin_example Example
289
290
The source of the dSS comes with an example implementation of a simulated dSID. This dSID simulates a mediaplayer device and controls a running VLC player. Its source can be found at "examples/plugins/vlc_remote". To try it out start a vlc instance with the following line:
291
292
\verbatim
293
vlc --rc-host localhost:4212
294
\endverbatim
295
296
\section notice Legal notice
297
298
Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
299
Copyright (c) 2009 futureLAB AG, Zurich, Switzerland
300
301
  This file is part of digitalSTROM Server.
302
303
  digitalSTROM Server is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
304
305
digitalSTROM Server is provided by the copyright holders and contributors “as is” and any expressed or implied warranties, including but not limited to the implied warranties of merchantability and fitness for a particular purpose are disclaimed.  In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary or consequential damages (including but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or Tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. Because some states do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you. In such states, digitalSTROM.org liability is limited to the greatest extent permitted by law
306
307
*/