implemented output module to output stream to character device
Stefan Schuermans

Stefan Schuermans commited on 2011-12-11 21:52:28
Showing 9 changed files, with 326 additions and 0 deletions.

... ...
@@ -85,6 +85,7 @@
85 85
       The following module types are available for instantiation:
86 86
       <ul>
87 87
         <li><a href="canvas.html">Canvas</a></li>
88
+        <li><a href="output.html">Output</a></li>
88 89
         <li><a href="player.html">Player</a></li>
89 90
         <li><a href="printer.html">Printer</a></li>
90 91
         <li><a href="priority.html">Priority</a></li>
... ...
@@ -0,0 +1,52 @@
1
+<html>
2
+  <head>
3
+    <title>Blinker - Output</title>
4
+  </head>
5
+  <body>
6
+    <h1>Blinker - Output</h1>
7
+    <p>
8
+      The output module receives a stream and outputs it to a character
9
+      device, e.g. a serial port.
10
+    </p>
11
+    <h2>Configuration</h2>
12
+    <p>
13
+      The configuration of the output module with name <code>NAME</code>
14
+      is located in the <code>outputs/NAME</code> subdirectory.
15
+    </p>
16
+    <h3>Input Stream</h3>
17
+    <p>
18
+      The file <code>instream</code> contains the name of the stream to
19
+      read.
20
+      The frames received from this stream are written to the character
21
+      device.
22
+    </p>
23
+    <h3>Protocol</h3>
24
+    <p>
25
+      The protocol to use is configured in the file <code>protocol</code>.
26
+      It can contain the string <code>blp</code>, <code>eblp</code> or
27
+      <code>mcuf</code> to select the BLP, EBLP or MCUF protocol respectively.
28
+    </p>
29
+    <h3>Device</h3>
30
+    <p>
31
+      The name of the character device to output the stream to is
32
+      configured in the file <code>device</code>.
33
+    </p>
34
+    <h3>Serial Port Configuration</h3>
35
+    <p>
36
+      If the device is a serial port, it can be configured by writing
37
+      a configuration string to the file <code>ser_cfg</code>.
38
+      The configuration string has to be in the format
39
+      <code>&lt;baudrate&gt;,&lt;data bits&gt;,&lt;parity&gt;,&lt;stop bits&gt;</code>
40
+      or 
41
+      <code>&lt;baudrate&gt;,&lt;parity&gt;,&lt;data bits&gt;,&lt;stop bits&gt;</code>.
42
+      The parity setting uses <code>N</code> for no parity, <code>E</code>
43
+      for even parity and <code>O</code> for odd parity.
44
+      The other settings are positive integer numbers.
45
+      <br>
46
+      If the device is not a serial port, the file <code>ser_cfg</code>
47
+      should not exist.
48
+      In this case, no serial port configuration of the device is done.
49
+    </p>
50
+  </body>
51
+</html>
52
+
... ...
@@ -0,0 +1,177 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <string>
7
+
8
+#include <BlinkenLib/BlinkenFrame.h>
9
+#include <BlinkenLib/BlinkenProto.h>
10
+
11
+#include "CallMgr.h"
12
+#include "Device.h"
13
+#include "Directory.h"
14
+#include "File.h"
15
+#include "InStreamFile.h"
16
+#include "Module.h"
17
+#include "NameFile.h"
18
+#include "Output.h"
19
+#include "Protocol.h"
20
+#include "ProtocolFile.h"
21
+#include "SerCfgFile.h"
22
+#include "StreamMgr.h"
23
+#include "StreamRecv.h"
24
+#include "TimeCallee.h"
25
+
26
+namespace Blinker {
27
+
28
+/**
29
+ * @brief constructor
30
+ * @param[in] callMgr callback manager
31
+ * @param[in] streamMgr stream manager
32
+ * @param[in] dirBase base directory
33
+ */
34
+Output::Output(CallMgr &callMgr, StreamMgr &streamMgr,
35
+               const Directory &dirBase):
36
+  Module(callMgr, streamMgr, dirBase),
37
+  m_fileInStream(dirBase.getFile("instream"), streamMgr),
38
+  m_fileProtocol(dirBase.getFile("protocol")),
39
+  m_fileDevice(dirBase.getFile("device")),
40
+  m_fileSerCfg(dirBase.getFile("ser_cfg"))
41
+{
42
+  // set up
43
+  m_fileInStream.setStreamRecv(this);
44
+  readProto();
45
+  openDevice();
46
+}
47
+
48
+/// virtual destructor
49
+Output::~Output()
50
+{
51
+  // clean up
52
+  closeDevice();
53
+  m_fileInStream.setStreamRecv(NULL);
54
+  m_callMgr.cancelTimeCall(this);
55
+}
56
+
57
+/// check for update of configuration
58
+void Output::updateConfig()
59
+{
60
+  // input stream name file was modified -> re-get input stream
61
+  if (m_fileInStream.checkModified())
62
+    m_fileInStream.update();
63
+
64
+  // protocol file was modified -> re-read protocol
65
+  if (m_fileProtocol.checkModified())
66
+    readProto();
67
+
68
+  // device file or serial settings file was modified -> re-open device
69
+  if (m_fileDevice.checkModified() || m_fileSerCfg.checkModified())
70
+    openDevice();
71
+}
72
+
73
+/**
74
+ * @brief set current frame
75
+ * @param[in] stream stream name
76
+ * @param[in] pFrame current frame (NULL for none)
77
+ */
78
+void Output::setFrame(const std::string &stream, stBlinkenFrame *pFrame)
79
+{
80
+  outputFrame();
81
+  (void)stream; // unused
82
+  (void)pFrame; // unused
83
+}
84
+
85
+/// callback when requested time reached
86
+void Output::timeCall()
87
+{
88
+  // if device is not open, try to (re-)open it
89
+  if (!m_pDevice)
90
+    openDevice();
91
+
92
+  // re-output current frame
93
+  outputFrame();
94
+}
95
+
96
+/// (re-)read protocol
97
+void Output::readProto()
98
+{
99
+  // update protocol from file
100
+  m_fileProtocol.update();
101
+
102
+  // re-output current frame using new protocol
103
+  outputFrame();
104
+}
105
+
106
+/// open device
107
+void Output::openDevice()
108
+{
109
+  closeDevice();
110
+
111
+  // get new device name and new serial config
112
+  m_fileDevice.update();
113
+  m_fileSerCfg.update();
114
+
115
+  // open device
116
+  if (m_fileDevice.m_valid)
117
+    m_pDevice = new Device(m_fileDevice.m_obj.m_str);
118
+
119
+  // serial config available -> configure serial port
120
+  if (m_pDevice && m_fileSerCfg.m_valid) {
121
+    if (!m_pDevice->setSerCfg(m_fileSerCfg.m_obj))
122
+      closeDevice(); // error -> close device
123
+  }
124
+
125
+  // output current frame to device
126
+  outputFrame();
127
+}
128
+
129
+/// close device
130
+void Output::closeDevice()
131
+{
132
+  // close device
133
+  if (m_pDevice) {
134
+    delete m_pDevice;
135
+    m_pDevice = NULL;
136
+  }
137
+
138
+  // request time callback in one second (for trying to re-open device)
139
+  m_callMgr.requestTimeCall(this, Time::now() + Time(1));
140
+}
141
+
142
+/// output current frame to device
143
+void Output::outputFrame()
144
+{
145
+  stBlinkenFrame *pFrame;
146
+  char buf[65536];
147
+  int len;
148
+  std::string data;
149
+
150
+  // no protocol or no device -> leave
151
+  if (!m_fileProtocol.m_valid || !m_pDevice)
152
+    return;
153
+
154
+  // get current frame from input stream
155
+  pFrame = m_fileInStream.getCurFrame();
156
+
157
+  // convert frame to protocol data
158
+  if (pFrame)
159
+    len = BlinkenFrameToNetwork(pFrame, m_fileProtocol.m_obj.m_proto,
160
+                                buf, sizeof(buf));
161
+  else
162
+    len = BlinkenProtoMakePacket(m_fileProtocol.m_obj.m_proto,
163
+                                 BlinkenPacketStreamEnd, buf, sizeof(buf));
164
+  if (len < 0)
165
+    len = 0;
166
+  data.assign(buf, len);
167
+
168
+  // output data to device
169
+  if (!m_pDevice->write(data))
170
+    closeDevice(); // error -> close device
171
+
172
+  // request time callback in one second (for outputting current frame again)
173
+  m_callMgr.requestTimeCall(this, Time::now() + Time(1));
174
+}
175
+
176
+} // namespace Blinker
177
+
... ...
@@ -0,0 +1,89 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef OUTPUT_H
7
+#define OUTPUT_H
8
+
9
+#include <string>
10
+
11
+#include <BlinkenLib/BlinkenFrame.h>
12
+
13
+#include "CallMgr.h"
14
+#include "Device.h"
15
+#include "Directory.h"
16
+#include "File.h"
17
+#include "InStreamFile.h"
18
+#include "Module.h"
19
+#include "NameFile.h"
20
+#include "Protocol.h"
21
+#include "ProtocolFile.h"
22
+#include "SerCfgFile.h"
23
+#include "StreamMgr.h"
24
+#include "StreamRecv.h"
25
+#include "TimeCallee.h"
26
+
27
+namespace Blinker {
28
+
29
+/// output of a stream to a device
30
+class Output: public Module, public StreamRecv, public TimeCallee
31
+{
32
+public:
33
+  /**
34
+   * @brief constructor
35
+   * @param[in] callMgr callback manager
36
+   * @param[in] streamMgr stream manager
37
+   * @param[in] dirBase base directory
38
+   */
39
+  Output(CallMgr &callMgr, StreamMgr &streamMgr, const Directory &dirBase);
40
+
41
+  /// virtual destructor
42
+  virtual ~Output();
43
+
44
+private:
45
+  /// copy constructor disabled
46
+  Output(const Output &that);
47
+
48
+  /// assignment operator disabled
49
+  const Output & operator=(const Output &that);
50
+
51
+public:
52
+  /// check for update of configuration
53
+  virtual void updateConfig();
54
+
55
+  /**
56
+   * @brief set current frame
57
+   * @param[in] stream stream name
58
+   * @param[in] pFrame current frame (NULL for none)
59
+   */
60
+  virtual void setFrame(const std::string &stream, stBlinkenFrame *pFrame);
61
+
62
+  /// callback when requested time reached
63
+  virtual void timeCall();
64
+
65
+protected:
66
+  /// (re-)read protocol
67
+  void readProto();
68
+
69
+  /// open device
70
+  void openDevice();
71
+
72
+  /// close device
73
+  void closeDevice();
74
+
75
+  /// output current frame to device
76
+  void outputFrame();
77
+
78
+protected:
79
+  InStreamFile m_fileInStream; ///< input stream name file
80
+  ProtocolFile m_fileProtocol; ///< protocol file
81
+  NameFile     m_fileDevice;   ///< name file containning name of device
82
+  SerCfgFile   m_fileSerCfg;   ///< serial port configuration file
83
+  Device       *m_pDevice;     ///< device to output to
84
+}; // class Output
85
+
86
+} // namespace Blinker
87
+
88
+#endif // #ifndef OUTPUT_H
89
+
... ...
@@ -11,6 +11,7 @@
11 11
 #include "Directory.h"
12 12
 #include "ModuleMgr.h"
13 13
 #include "ModuleMgr_impl.h"
14
+#include "Output.h"
14 15
 #include "Player.h"
15 16
 #include "Printer.h"
16 17
 #include "Priority.h"
... ...
@@ -30,6 +31,8 @@ void run(const std::string &dirConfig)
30 31
 
31 32
   ModuleMgr<Canvas> canvasMgr(callMgr, streamMgr,
32 33
                               dirCfg.getSubdir("canvases"));
34
+  ModuleMgr<Output> outputMgr(callMgr, streamMgr,
35
+                              dirCfg.getSubdir("outputs"));
33 36
   ModuleMgr<Player> playerMgr(callMgr, streamMgr,
34 37
                               dirCfg.getSubdir("players"));
35 38
   ModuleMgr<Printer> printerMgr(callMgr, streamMgr,
36 39