fujikininterface.cpp
1 #include "fujikininterface.h"
2 
3 std::deque<weak_ptr<XPort> > XFujikinInterface::s_openedPorts;
4 XMutex XFujikinInterface::s_lock;
5 
6 XFujikinInterface::XFujikinInterface(const char *name, bool runtime, const shared_ptr<XDriver> &driver) :
7  XCharInterface(name, runtime, driver) {
8  setEOS("");
9  setSerialEOS("");
10  setSerialBaudRate(38400);
11  setSerialStopBits(1);
12 }
13 
14 XFujikinInterface::~XFujikinInterface() {
15 }
16 
17 void
18 XFujikinInterface::open() throw (XInterfaceError &) {
19  XScopedLock<XFujikinInterface> lock( *this);
20  {
21  Snapshot shot( *this);
22  XScopedLock<XMutex> glock(s_lock);
23  for(auto it = s_openedPorts.begin(); it != s_openedPorts.end();) {
24  if(auto pt = it->lock()) {
25  if(pt->portString() == (XString)shot[ *port()]) {
26  m_openedPort = pt;
27  //The COMM port has been already opened by m_master.
28  return;
29  }
30  ++it;
31  }
32  else
33  it = s_openedPorts.erase(it); //cleans garbage.
34  }
35  }
36  //Opens new COMM device.
37  XCharInterface::open();
38  m_openedPort = openedPort();
39  s_openedPorts.push_back(m_openedPort);
40 }
41 void
42 XFujikinInterface::close() throw (XInterfaceError &) {
43  XScopedLock<XFujikinInterface> lock( *this);
44  XScopedLock<XMutex> glock(s_lock);
45  m_openedPort.reset(); //release shared_ptr to the port if any.
46  XCharInterface::close(); //release shared_ptr to the port if any.
47 }
48 
49 template <typename T>
50 void
51 XFujikinInterface::send(uint8_t classid, uint8_t instanceid, uint8_t attributeid, T data) {
52 }
53 template <>
54 void
55 XFujikinInterface::send(uint8_t classid, uint8_t instanceid, uint8_t attributeid, uint8_t data) {
56 std::vector<uint8_t> wbuf(1);
57  wbuf[0] = data;
58  communicate(classid, instanceid, attributeid, wbuf);
59 }
60 template <>
61 void
62 XFujikinInterface::send(uint8_t classid, uint8_t instanceid, uint8_t attributeid, uint16_t data) {
63 std::vector<uint8_t> wbuf(2);
64  wbuf[0] = data % 0x100u;
65  wbuf[1] = data / 0x100u;
66  communicate(classid, instanceid, attributeid, wbuf);
67 }
68 template <>
69 void
70 XFujikinInterface::send(uint8_t classid, uint8_t instanceid, uint8_t attributeid, uint32_t data) {
71 std::vector<uint8_t> wbuf(4);
72  wbuf[0] = data % 0x100u;
73  wbuf[1] = (data / 0x100uL) % 0x100u;
74  wbuf[1] = (data / 0x10000uL) % 0x100u;
75  wbuf[1] = data / 0x1000000uL;
76  communicate(classid, instanceid, attributeid, wbuf);
77 }
78 template <typename T>
79 T
80 XFujikinInterface::query(uint8_t classid, uint8_t instanceid, uint8_t attributeid) {
81 }
82 template <>
83 uint8_t
84 XFujikinInterface::query(uint8_t classid, uint8_t instanceid, uint8_t attributeid) {
85  std::vector<uint8_t> wbuf(0), rbuf;
86  communicate(classid, instanceid, attributeid, wbuf, &rbuf);
87  if(rbuf.size() != 1)
88  throw XInterfaceError("Fujikin Protocol Wrong Data-Size Error.", __FILE__, __LINE__);
89  return rbuf[0];
90 }
91 template <>
92 uint16_t
93 XFujikinInterface::query(uint8_t classid, uint8_t instanceid, uint8_t attributeid) {
94  std::vector<uint8_t> wbuf(0), rbuf;
95  communicate(classid, instanceid, attributeid, wbuf, &rbuf);
96  if(rbuf.size() != 2)
97  throw XInterfaceError("Fujikin Protocol Wrong Data-Size Error.", __FILE__, __LINE__);
98  return rbuf[0] + (uint16_t)rbuf[1] * 0x100u;
99 }
100 template <>
101 XString
102 XFujikinInterface::query(uint8_t classid, uint8_t instanceid, uint8_t attributeid) {
103  std::vector<uint8_t> wbuf(0), rbuf;
104  communicate(classid, instanceid, attributeid, wbuf, &rbuf);
105  rbuf.push_back(0); //null
106  return reinterpret_cast<char *>( &rbuf[0]);
107 }
108 void
109 XFujikinInterface::communicate(uint8_t classid, uint8_t instanceid, uint8_t attributeid,
110  const std::vector<uint8_t> &data, std::vector<uint8_t> *response) {
111  for(int retry = 0; ; retry++) {
112  try {
113  communicate_once(classid, instanceid, attributeid, data, response);
114  break;
115  }
116  catch (XInterfaceError &e) {
117  if(retry < 1) {
118  e.print("Retrying after an error: ");
119  msecsleep(20);
120  continue;
121  }
122  throw e;
123  }
124  }
125 }
126 void
127 XFujikinInterface::communicate_once(uint8_t classid, uint8_t instanceid, uint8_t attributeid,
128  const std::vector<uint8_t> &data, std::vector<uint8_t> *response) {
129 
130  bool write = !response;
131  std::vector<uint8_t> buf;
132  buf.push_back( ***address());
133  buf.push_back(STX);
134  uint8_t commandcode = write ? 0x81 : 0x80;
135  buf.push_back(commandcode);
136  buf.push_back(3 + data.size());
137  buf.push_back(classid);
138  buf.push_back(instanceid);
139  buf.push_back(attributeid);
140  for(auto it = data.begin(); it != data.end(); ++it)
141  buf.push_back( *it);
142  buf.push_back(0); //pad
143  uint8_t checksum = 0;
144  for(auto it = buf.begin() + 1; it != buf.end(); ++it)
145  checksum += *it; //from STX to data.back.
146  buf.push_back(checksum);
147 
148  auto port = m_openedPort;
149  XScopedLock<XMutex> lock(s_lock); //!\todo better to use port-by-port lock.
150  msecsleep(1);
151  port->write( reinterpret_cast<char*>( &buf[0]), buf.size());
152  port->receive(1);
153  switch(port->buffer()[0]) {
154  case ACK:
155  break;
156  case NAK:
157  default:
158  throw XInterfaceError(
159  formatString("Fujikin Protocol Command Error ret=%x.", (unsigned int)port->buffer()[0]),
160  __FILE__, __LINE__);
161  }
162  if(write) {
163  port->receive(1);
164  switch(port->buffer()[0]) {
165  case ACK:
166  break;
167  case NAK:
168  default:
169  throw XInterfaceError(
170  formatString("Fujikin Protocol Command Error ret=%x.", (unsigned int)port->buffer()[0]),
171  __FILE__, __LINE__);
172  }
173  }
174  else {
175  port->receive(4);
176  if((port->buffer()[0] != 0) || (port->buffer()[1] != STX))
177  throw XInterfaceError(
178  formatString("Fujikin Protocol Command Error ret=%4s.", (const char*)&port->buffer()[0]),
179  __FILE__, __LINE__);
180  int len = port->buffer()[3];
181  uint8_t checksum = 0;
182  for(auto it = port->buffer().begin(); it != port->buffer().end(); ++it)
183  checksum += *it;
184  port->receive(len + 2);
185 // if((master->buffer()[0] != classid) || (master->buffer()[1] != instanceid) || (master->buffer()[2] != attributeid))
186 // throw XInterfaceError("Fujikin Protocol Format Error.", __FILE__, __LINE__);
187  if((port->buffer()[len] != 0)) //pad
188  throw XInterfaceError("Fujikin Protocol Format Error.", __FILE__, __LINE__);
189  for(auto it = port->buffer().begin(); it != port->buffer().end(); ++it)
190  checksum += *it;
191  checksum -= port->buffer().back() * 2;
192  if(checksum != 0)
193  throw XInterfaceError("Fujikin Protocol Check-Sum Error.", __FILE__, __LINE__);
194  response->resize(len - 3);
195  for(int i = 0; i < response->size(); ++i) {
196  response->at(i) = port->buffer()[i + 3];
197  }
198  }
199 }

Generated for KAME4 by  doxygen 1.8.3