1 #include "uldy_server.h"
5 extern CidPool cidPool;
7 bool AddressPool::blockAddress(long sn, int addr) {
8 if (!assignedAddrs.contains(sn) && !assignedAddrs.values().contains(addr)) {
9 assignedAddrs.insert(sn, addr);
15 int AddressPool::getFreeAddress(long sn) {
16 // return 60; // DOCASNE
17 if (assignedAddrs.size() == MAX_ADDR) return 0;
19 if (holes.size() == 0) {
20 retval = assignedAddrs.size() + 1;
22 QMutableSetIterator<int> it(holes);
27 assignedAddrs.insert(sn, retval);
31 void AddressPool::freeAddress(long sn) {
33 if (assignedAddrs.contains(sn)) {
34 int addr = assignedAddrs.value(sn);
35 if (addr != assignedAddrs.size())
37 assignedAddrs.remove(sn);
40 AddressPool addressPool;
43 void ULDYServer::sendNewAddress(int addr, long sn) const {
46 ul_fd_t ul_fd = ul_open(UL_DEV_NAME, NULL);
47 if (ul_fd == UL_FD_INVALID) {
48 logToFile("[EE] ULDYSRV - chyba pri zasilani adresy: neplatny deskriptor...");
51 buf_out.append(ULNCS_SET_ADDR); /* SN0 SN1 SN2 SN3 NEW_ADR */
52 buf_out += sn2buf(sn);
54 ret = ul_send_command(ul_fd, 0, UL_CMD_NCS, UL_BFL_NORE, (uchar*)buf_out.constData(), buf_out.size()); //UL_BFL_ARQ
55 // logToFile(QString("[II] odeslana zprava, status: %1, len: %2 data %3").arg(ret).arg(buf_out.size()).arg(buf_out.toHex().constData()));
59 void ULDYServer::requestIdentification(int addr) const {
62 ul_fd_t ul_fd = ul_open(UL_DEV_NAME, NULL);
63 if (ul_fd == UL_FD_INVALID) {
64 logToFile("[EE] ULDYSRV - chyba pri dotazu na identifikaci: neplatny deskriptor...");
67 buf_out.append(ULNCS_SID_RQ);
68 ret = ul_send_command(ul_fd, addr, UL_CMD_NCS, UL_BFL_NORE, (uchar*)buf_out.constData(), buf_out.size()); //UL_BFL_ARQ
69 logToFile(QString("[II] odeslana zadost o identifikaci na adresu %1").arg(addr));
73 void ULDYServer::processPDOMessage(int saddr, int cid, int data) {
74 // logToFile(QString("PDO msg: CID = %1, DATA = %2").arg(cid).arg(data));
75 if (nodes.contains(saddr)) {
76 Node &node = nodes.getNodeRef(saddr);
77 if (cid == HEARTBEAT_CID) {
79 logToFile(QString("[II] - HEARTBEAT from address %1").arg(saddr));
80 node.refreshLastUpdate();
85 NodeVar tmpVar = node.hasCid(cid);
86 float fdata = ((float)data) / pow(10.0, (double)tmpVar.getDecimalPlaces());
87 valueCache.insertValue(node.getSN(), tmpVar.getId(), fdata);
88 } catch (NodeVarError) { }
89 node.refreshLastUpdate();
92 } else if (saddr != NOT_ASSIGNED_ADDR) {
94 requestIdentification(saddr);
97 // logToFile(QString("PDO zpracovana %1").arg((unsigned long)QThread::currentThreadId()));
100 void ULDYServer::stopServer(void) {
101 logToFile("[II] ULDYSRV - stopping uldy server...");
102 this->running = false;
105 void ULDYServer::run() {
107 int addr, saddr, msg_len;
115 Node *newNode = new Node(30, 102);
116 this->nodes.insert(30, newNode);
118 while (this->running) {
120 int data = getRandom();
122 processPDOMessage(30, cid, data);
125 ul_fd_t ul_fd = ul_open(UL_DEV_NAME, NULL);
126 if (ul_fd == UL_FD_INVALID) {
127 logToFile("[EE] ULDYSRV - neplatny deskriptor");
131 memset(&msginfo, 0, sizeof(ul_msginfo));
132 ul_addfilt(ul_fd, &msginfo);
134 logToFile("[II] ULDYSRV - cekam na zpravu...");
136 while (this->running) { // main loop
138 while ((ul_fd_wait(ul_fd, 1) <= 0) && this->running) ;
140 if ((ul_inepoll(ul_fd) > 0) && (ul_acceptmsg(ul_fd, &msginfo)) >= 0) {
141 if (msginfo.cmd == UL_CMD_NCS) {
142 msg_len = msginfo.len;
143 saddr = msginfo.sadr;
144 buf_in.resize(msg_len);
145 ret = ul_read(ul_fd, buf_in.data(), msg_len); // nacteni SN do bufferu
146 // logToFile(QString("[II] prijata zprava, sadr: %1, dadr: %2, len: %3 data %4").arg(msginfo.sadr).arg(msginfo.dadr).arg(msginfo.len).arg(buf_in.toHex().constData()));
148 switch ((uchar)buf_in[0]) {
152 logToFile(QString("[WW] ULDYSRV - neplatna zadost o adresu, ocekavam delku minimalne 5").arg(msg_len));
155 // logToFile(QString("[II] prijmam zadost o adresu, SN %1").arg(sn));
156 if ((addr = addressPool.getFreeAddress(sn)) != 0) {
157 logToFile(QString("[II] ULDYSRV - sending new address \"%1\" to SN \"%2\"...").arg(addr).arg(sn));
158 if (!(this->nodes.contains(addr))) {
159 sendNewAddress(addr, sn);
160 Node *newNode = new Node(addr, sn);
161 this->nodes.insert(addr, newNode);
162 logToFile(QString("[II] mapa nodu nyni obsahuje %1 polozek...").arg(this->nodes.size()));
163 } else { logToFile("nod uz tam je"); }
165 logToFile("[WW] ULDYSRV - address pool is full, try again later, please...");
170 logToFile(QString("[II] - received identification from unknown node, addr %1").arg(saddr));
171 if (!(this->nodes.contains(saddr))) {
172 Node *newNode = new Node(saddr, sn);
173 addressPool.blockAddress(sn, saddr);
174 this->nodes.insert(saddr, newNode);
175 logToFile(QString("[II] mapa nodu nyni obsahuje %1 polozek...").arg(this->nodes.size()));
176 } else { logToFile("nod uz tam je"); }
183 } else if (msginfo.cmd == UL_CMD_PDO) {
184 msg_len = msginfo.len;
185 saddr = msginfo.sadr;
186 buf_in.resize(msg_len);
187 ret = ul_read(ul_fd, buf_in.data(), msg_len);
190 buf_in = buf_in.mid(PDO_SKIP_BYTES);
195 int cid = takeCid(buf_in, &success);
198 int len = takeLen(buf_in, &success);
201 int data = takeData(buf_in, len, &success);
204 processPDOMessage(saddr, cid, data);
209 } /* ul_inepool && ul_acceptmsg */
211 } /* while(running) */
215 int ULDYServer::takeCid(QByteArray &buf, bool *success) const {
216 if (buf.size() < 2) { *success = false; /*logToFile("nedostatecna delka CID");*/ return 0; }
217 int ret = buf2uint16(buf);
223 int ULDYServer::takeLen(QByteArray &buf, bool *success) const {
224 // return takeCid(buf, success);
225 if (buf.size() < 2) { *success = false; /*logToFile("nedostatecna delka LEN");*/ return 0; }
227 int ret = buf2uint16(buf);
233 int ULDYServer::takeData(QByteArray &buf, int len, bool *success) const {
234 if (buf.size() < len) { *success = false; return 0; }
236 for (int i = 0; i < len; i++) {
237 ret += (uchar)buf[i]<<(i * 8);
244 const NodeMap &ULDYServer::getNodes() const {
248 NodeMap &ULDYServer::getNodesRef() {
252 ValueCache &ULDYServer::getValueCacheRef() {
253 return this->valueCache;
256 void ULDYServer::tryRemoveNodes() {
257 NodeMapMutableIterator it(this->nodes);
258 QDateTime curr, last;
259 while (it.hasNext()) {
262 curr = currentDateTime();
263 last = this->nodes.getNodeRef(addr).getLastUpdate();
264 last.setTimeSpec(Qt::UTC);
265 if ((curr.toTime_t() - last.toTime_t()) > NODE_CLEANER_PERIOD_SECS) {
266 logToFile(QString("[II] - Removing node SN %1...").arg(this->nodes.getNodeRef(addr).getSN()));
267 addressPool.freeAddress(this->nodes.getNodeRef(addr).getSN());
268 cidPool.freeCids(this->nodes.getNodeRef(addr).getUsedCidsRef());
269 Node *tmpNode = this->nodes.value(addr);
270 this->nodes.remove(addr);