Line |
Branch |
Exec |
Source |
1 |
|
|
/***************************************************************************** |
2 |
|
|
* |
3 |
|
|
* $Id$ |
4 |
|
|
* |
5 |
|
|
* Copyright 2010 Richard Hacker (lerichi at gmx dot net) |
6 |
|
|
* |
7 |
|
|
* This file is part of the pdserv library. |
8 |
|
|
* |
9 |
|
|
* The pdserv library is free software: you can redistribute it and/or modify |
10 |
|
|
* it under the terms of the GNU Lesser General Public License as published |
11 |
|
|
* by the Free Software Foundation, either version 3 of the License, or (at |
12 |
|
|
* your option) any later version. |
13 |
|
|
* |
14 |
|
|
* The pdserv library is distributed in the hope that it will be useful, but |
15 |
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
16 |
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
17 |
|
|
* License for more details. |
18 |
|
|
* |
19 |
|
|
* You should have received a copy of the GNU Lesser General Public License |
20 |
|
|
* along with the pdserv library. If not, see <http://www.gnu.org/licenses/>. |
21 |
|
|
* |
22 |
|
|
*****************************************************************************/ |
23 |
|
|
|
24 |
|
|
#include "Parameter.h" |
25 |
|
|
#include "XmlElement.h" |
26 |
|
|
#include "Session.h" |
27 |
|
|
#include "../Parameter.h" |
28 |
|
|
#include "../Debug.h" |
29 |
|
|
#include "../DataType.h" |
30 |
|
|
|
31 |
|
|
#include <sstream> |
32 |
|
|
#include <cerrno> |
33 |
|
|
#include <stdint.h> |
34 |
|
|
|
35 |
|
|
#define MSR_R 0x01 /* Parameter is readable */ |
36 |
|
|
#define MSR_W 0x02 /* Parameter is writeable */ |
37 |
|
|
#define MSR_WOP 0x04 /* Parameter is writeable in real-time */ |
38 |
|
|
//#define MSR_MONOTONIC 0x8 /* List must be monotonic */ |
39 |
|
|
//#define MSR_S 0x10 /* Parameter must be saved by clients */ |
40 |
|
|
#define MSR_G 0x20 /* Gruppenbezeichnung (unused) */ |
41 |
|
|
#define MSR_AW 0x40 /* Writeable by admin only */ |
42 |
|
|
#define MSR_P 0x80 /* Persistant parameter, written to disk */ |
43 |
|
|
#define MSR_DEP 0x100 /* This parameter is an exerpt of another parameter. |
44 |
|
|
Writing to this parameter also causes an update |
45 |
|
|
notice for the encompassing parameter */ |
46 |
|
|
#define MSR_AIC 0x200 /* Asynchronous input channel */ |
47 |
|
|
|
48 |
|
|
/* ein paar Kombinationen */ |
49 |
|
|
#define MSR_RWS (MSR_R | MSR_W | MSR_S) |
50 |
|
|
#define MSR_RP (MSR_R | MSR_P) |
51 |
|
|
|
52 |
|
|
|
53 |
|
|
using namespace MsrProto; |
54 |
|
|
|
55 |
|
|
///////////////////////////////////////////////////////////////////////////// |
56 |
|
✗ |
Parameter::Parameter(const PdServ::Parameter *p, size_t index, |
57 |
|
|
const PdServ::DataType& dtype, |
58 |
|
|
const PdServ::DataType::DimType& dim, |
59 |
|
✗ |
size_t offset, Parameter *parent): |
60 |
|
|
Variable(p, index, dtype, dim, offset, parent), |
61 |
|
|
mainParam(p), |
62 |
|
✗ |
dependent(parent != 0) |
63 |
|
|
{ |
64 |
|
|
} |
65 |
|
|
|
66 |
|
|
///////////////////////////////////////////////////////////////////////////// |
67 |
|
✗ |
void Parameter::setXmlAttributes(XmlElement &element, const char *valueBuf, |
68 |
|
|
struct timespec const& mtime, bool shortReply, bool hex, |
69 |
|
|
size_t precision) const |
70 |
|
|
{ |
71 |
|
✗ |
unsigned int flags = MSR_R | MSR_W | MSR_WOP; |
72 |
|
|
|
73 |
|
|
// <parameter name="/lan/Control/EPC/EnableMotor/Value/2" |
74 |
|
|
// index="30" value="0"/> |
75 |
|
|
|
76 |
|
✗ |
setAttributes(element, shortReply); |
77 |
|
|
|
78 |
|
✗ |
if (!shortReply) { |
79 |
|
✗ |
XmlElement::Attribute(element, "flags") |
80 |
|
✗ |
<< flags + (dependent ? 0x100 : 0); |
81 |
|
|
|
82 |
|
|
// persistent= |
83 |
|
✗ |
if (mainParam->persistent) |
84 |
|
✗ |
XmlElement::Attribute(element, "persistent") << 1; |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
// mtime= |
88 |
|
✗ |
XmlElement::Attribute(element, "mtime") << mtime; |
89 |
|
|
|
90 |
|
✗ |
if (valueBuf) { |
91 |
|
✗ |
if (hex) |
92 |
|
✗ |
XmlElement::Attribute(element, "hexvalue") |
93 |
|
✗ |
.hexDec(valueBuf + offset, dtype.size); |
94 |
|
|
else |
95 |
|
✗ |
XmlElement::Attribute(element, "value").csv( this, |
96 |
|
✗ |
valueBuf + offset, 1, precision); |
97 |
|
|
} |
98 |
|
|
|
99 |
|
✗ |
addCompoundFields(element, variable->dtype); |
100 |
|
|
|
101 |
|
✗ |
return; |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
///////////////////////////////////////////////////////////////////////////// |
105 |
|
✗ |
int Parameter::setHexValue(const Session *session, |
106 |
|
|
const char *s, size_t startindex, size_t &count) const |
107 |
|
|
{ |
108 |
|
✗ |
char valueBuf[memSize]; |
109 |
|
✗ |
const char *valueEnd = valueBuf + memSize; |
110 |
|
|
static const char hexNum[] = { |
111 |
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, |
112 |
|
|
0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
113 |
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
114 |
|
|
0,10,11,12,13,14,15 |
115 |
|
|
}; |
116 |
|
|
|
117 |
|
|
char *c; |
118 |
|
✗ |
for (c = valueBuf; *s and c < valueEnd; c++) { |
119 |
|
✗ |
unsigned char c1 = *s++ - '0'; |
120 |
|
✗ |
unsigned char c2 = *s++ - '0'; |
121 |
|
✗ |
if (std::max(c1,c2) >= sizeof(hexNum)) |
122 |
|
✗ |
return -EINVAL; |
123 |
|
✗ |
*c = hexNum[c1] << 4 | hexNum[c2]; |
124 |
|
|
} |
125 |
|
|
// FIXME: actually the setting operation must also check for |
126 |
|
|
// endianness! |
127 |
|
|
|
128 |
|
✗ |
count = c - valueBuf; |
129 |
|
✗ |
return mainParam->setValue( session, valueBuf, |
130 |
|
✗ |
offset + startindex * dtype.size, count); |
131 |
|
|
} |
132 |
|
|
|
133 |
|
|
///////////////////////////////////////////////////////////////////////////// |
134 |
|
✗ |
int Parameter::setElements(std::istream& is, |
135 |
|
|
const PdServ::DataType& dtype, const PdServ::DataType::DimType& dim, |
136 |
|
|
char*& buf, size_t& count) const |
137 |
|
|
{ |
138 |
|
✗ |
if (dtype.primary() == dtype.compound_T) { |
139 |
|
✗ |
const PdServ::DataType::FieldList& fieldList = dtype.getFieldList(); |
140 |
|
✗ |
PdServ::DataType::FieldList::const_iterator it; |
141 |
|
✗ |
for (size_t i = 0; i < dim.nelem; ++i) { |
142 |
|
✗ |
for (it = fieldList.begin(); it != fieldList.end(); ++it) { |
143 |
|
✗ |
int rv = setElements(is, (*it)->type, (*it)->dim, buf, count); |
144 |
|
✗ |
if (rv) |
145 |
|
✗ |
return rv; |
146 |
|
|
} |
147 |
|
|
} |
148 |
|
✗ |
return 0; |
149 |
|
|
} |
150 |
|
|
|
151 |
|
✗ |
double v; |
152 |
|
✗ |
char c; |
153 |
|
✗ |
for (size_t i = 0; i < dim.nelem; ++i) { |
154 |
|
|
|
155 |
|
✗ |
is >> v; |
156 |
|
✗ |
if (!is) |
157 |
|
✗ |
return -EINVAL; |
158 |
|
|
|
159 |
|
✗ |
dtype.setValue(buf, v); |
160 |
|
✗ |
count += dtype.size; |
161 |
|
|
|
162 |
|
✗ |
is >> c; |
163 |
|
✗ |
if (!is) |
164 |
|
✗ |
return 1; |
165 |
|
|
|
166 |
|
✗ |
if (c != ',' and c != ';' and !isspace(c)) |
167 |
|
✗ |
return -EINVAL; |
168 |
|
|
} |
169 |
|
|
|
170 |
|
✗ |
return 0; |
171 |
|
|
} |
172 |
|
|
|
173 |
|
|
///////////////////////////////////////////////////////////////////////////// |
174 |
|
✗ |
int Parameter::setDoubleValue(const Session *session, |
175 |
|
|
const char *buf, size_t startindex, size_t &count) const |
176 |
|
|
{ |
177 |
|
✗ |
char valueBuf[memSize]; |
178 |
|
✗ |
char *dataBuf = valueBuf; |
179 |
|
|
|
180 |
|
✗ |
std::istringstream is(buf); |
181 |
|
✗ |
is.imbue(std::locale::classic()); |
182 |
|
|
|
183 |
|
|
//log_debug("buf=%s", buf); |
184 |
|
✗ |
count = 0; |
185 |
|
✗ |
int rv = setElements(is, dtype, dim, dataBuf, count); |
186 |
|
|
|
187 |
|
|
// log_debug("rv=%i startindex=%zu offset=%zu count=%zu", |
188 |
|
|
// rv, startindex, offset/dtype.size + startindex, count); |
189 |
|
|
// for (size_t i = 0; i < count; i++) |
190 |
|
|
// std::cerr << ((const double*)valueBuf)[i] << ' '; |
191 |
|
|
// std::cerr << std::endl; |
192 |
|
|
return rv < 0 |
193 |
|
✗ |
? rv |
194 |
|
✗ |
: mainParam->setValue( session, valueBuf, |
195 |
|
✗ |
offset + startindex * dtype.size, count); |
196 |
|
3 |
} |
197 |
|
|
|