Slupik98

TOD

Aug 10th, 2018
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.12 KB | None | 0 0
  1. #include "rs485v2.h"
  2.  
  3.  
  4. RS485v2::RS485v2()
  5. {
  6. this->config = new Config(this);
  7. this->foundDunaHeader = false;
  8.  
  9. serialPortName = config->getGlobal("module_rs485v2","serialPortName").toString();
  10. slowDataSend = config->getGlobal("module_rs485v2","SlowDataSend").toBool();
  11. allow7Seg = config->getGlobal("module_rs485v2","Allow7Seg").toBool();
  12. allowLCD = config->getGlobal("module_rs485v2","AllowLCD").toBool();
  13. enableClock = config->getGlobal("module_rs485v2","EnableClock").toBool();
  14.  
  15. this->serialPort = new QSerialPort(serialPortName,this);
  16. serialPort->setBaudRate(QSerialPort::Baud19200);
  17. serialPort->setFlowControl(QSerialPort::NoFlowControl);
  18.  
  19. serialPort->setParity(QSerialPort::NoParity);
  20. serialPort->setDataBits(QSerialPort::Data8);
  21. serialPort->setStopBits(QSerialPort::OneStop);
  22.  
  23. rs485Busy = false;
  24. if (serialPort->open(QIODevice::ReadWrite | QIODevice::Unbuffered) == true) {
  25. qDebug() << "ready to send data on" << serialPort->portName();
  26. connect(serialPort, SIGNAL(readyRead()), this, SLOT(onSerialDataAvailable()));
  27. } else {
  28. qDebug() << "device failed to open:" << serialPort->errorString();
  29. }
  30. }
  31.  
  32. RS485v2::~RS485v2()
  33. {
  34. this->serialPort->close();
  35. }
  36.  
  37. void RS485v2::sendDataTo7Seg(ZegarStatus zegarStatus, QString location)
  38. {
  39. if(!allow7Seg)
  40. return;
  41.  
  42. // wysłanie danych do wyświetlaczy
  43. QByteArray bufor;
  44. bufor.resize(13);
  45. bufor.fill(0);
  46.  
  47. // PRZYGOTOWANIE DANYCH DO WYSYŁKI
  48. bufor[0] = 0x02; // adres wyświetlacza - broadcast
  49. if(zegarStatus.kierunek == GORA || zegarStatus.przekroczony){
  50. bufor[1] = (quint8)(zegarStatus.czas_up / 60); // minuty
  51. bufor[2] = (quint8)(zegarStatus.czas_up % 60); // sekundy
  52. } else {
  53. bufor[1] = (quint8)(zegarStatus.czas_down / 60); // minuty
  54. bufor[2] = (quint8)(zegarStatus.czas_down % 60); // sekundy
  55. }
  56. if(bufor.at(1) > 99)
  57. bufor[1] = 99;
  58.  
  59. if(zegarStatus.warning)
  60. bufor[5] = 1;
  61. if(zegarStatus.przekroczony){
  62. //mrugać szybko
  63. //zapalić diodę informującą o przekroczeniu czasu
  64. bufor[6] = 1;
  65. }
  66. if(zegarStatus.stan_zegara == STAN_ZEGARA_STOPPED){
  67. bufor[4] = 1; // reset wyświetlacza
  68. if(this->enableClock){
  69. QDate data;
  70. QTime czas;
  71. data = QDate::currentDate();
  72. czas = QTime::currentTime();
  73.  
  74. bufor[8] = (quint8)czas.hour();
  75. bufor[9] = (quint8)czas.minute();
  76. bufor[10] = (quint8)czas.second();
  77. bufor[11] = (quint8)data.month();
  78. bufor[12] = (quint8)data.day();
  79. } else {
  80. // nie ma opcji zegara - wszystko na zero
  81. bufor[8] = 0;
  82. bufor[9] = 0;
  83. bufor[10] = 0;
  84. bufor[11] = 0;
  85. bufor[12] = 0;
  86. }
  87. }
  88. if(zegarStatus.wygaszaj_wiodace){
  89. bufor[3] = 1;
  90. }
  91.  
  92. if(zegarStatus.buzzer){
  93. if(zegarStatus.przekroczony){
  94. if(zegarStatus.czas_up == 1)
  95. bufor[7] = 1;
  96. if(zegarStatus.czas_up == 10)
  97. bufor[7] = 2;
  98. if(zegarStatus.czas_up == 20)
  99. bufor[7] = 20;
  100. bufor[6] = 1;
  101. }
  102. }
  103.  
  104. if(location.toUpper() == "A"){
  105. // display obsługuje tylko lokalizację w sali A
  106. this->sendData(bufor, 0x01);
  107. }
  108. }
  109.  
  110. void RS485v2::sendDataToLCD(LCD_Command lcd_command)
  111. {
  112. if(!allowLCD)
  113. return;
  114.  
  115. //wysyłanie do wyświetlaczy LCD
  116. quint8 i, poz, dl_linia;
  117. QByteArray bufor;
  118. bufor.resize(165);
  119. bufor.fill(' ');
  120. QByteArray tmp;
  121.  
  122. //linie wpisywane do bufora w kolejności 1-3-2-4
  123. //naturalna kolejność wyświetlacza LCD
  124.  
  125. lcd_command.linia1 = lcd_command.linia1.replace("_"," ");
  126. lcd_command.linia2 = lcd_command.linia2.replace("_"," ");
  127. lcd_command.linia3 = lcd_command.linia3.replace("_"," ");
  128. lcd_command.linia4 = lcd_command.linia4.replace("_"," ");
  129.  
  130. lcd_command.linia1 = lcd_command.linia1.replace("ń","n");
  131. lcd_command.linia2 = lcd_command.linia2.replace("ń","n");
  132. lcd_command.linia3 = lcd_command.linia3.replace("ń","n");
  133. lcd_command.linia4 = lcd_command.linia4.replace("ń","n");
  134.  
  135. lcd_command.linia1 = lcd_command.linia1.replace("ą","_a");
  136. lcd_command.linia2 = lcd_command.linia2.replace("ą","_a");
  137. lcd_command.linia3 = lcd_command.linia3.replace("ą","_a");
  138. lcd_command.linia4 = lcd_command.linia4.replace("ą","_a");
  139.  
  140. lcd_command.linia1 = lcd_command.linia1.replace("ć","_c");
  141. lcd_command.linia2 = lcd_command.linia2.replace("ć","_c");
  142. lcd_command.linia3 = lcd_command.linia3.replace("ć","_c");
  143. lcd_command.linia4 = lcd_command.linia4.replace("ć","_c");
  144.  
  145. lcd_command.linia1 = lcd_command.linia1.replace("ę","_e");
  146. lcd_command.linia2 = lcd_command.linia2.replace("ę","_e");
  147. lcd_command.linia3 = lcd_command.linia3.replace("ę","_e");
  148. lcd_command.linia4 = lcd_command.linia4.replace("ę","_e");
  149.  
  150. lcd_command.linia1 = lcd_command.linia1.replace("ł","_l");
  151. lcd_command.linia2 = lcd_command.linia2.replace("ł","_l");
  152. lcd_command.linia3 = lcd_command.linia3.replace("ł","_l");
  153. lcd_command.linia4 = lcd_command.linia4.replace("ł","_l");
  154.  
  155. lcd_command.linia1 = lcd_command.linia1.replace("ó","_o");
  156. lcd_command.linia2 = lcd_command.linia2.replace("ó","_o");
  157. lcd_command.linia3 = lcd_command.linia3.replace("ó","_o");
  158. lcd_command.linia4 = lcd_command.linia4.replace("ó","_o");
  159.  
  160. lcd_command.linia1 = lcd_command.linia1.replace("ś","_s");
  161. lcd_command.linia2 = lcd_command.linia2.replace("ś","_s");
  162. lcd_command.linia3 = lcd_command.linia3.replace("ś","_s");
  163. lcd_command.linia4 = lcd_command.linia4.replace("ś","_s");
  164.  
  165. lcd_command.linia1 = lcd_command.linia1.replace("ż","_z");
  166. lcd_command.linia2 = lcd_command.linia2.replace("ż","_z");
  167. lcd_command.linia3 = lcd_command.linia3.replace("ż","_z");
  168. lcd_command.linia4 = lcd_command.linia4.replace("ż","_z");
  169.  
  170. lcd_command.linia1 = lcd_command.linia1.replace("ź","_x");
  171. lcd_command.linia2 = lcd_command.linia2.replace("ź","_x");
  172. lcd_command.linia3 = lcd_command.linia3.replace("ź","_x");
  173. lcd_command.linia4 = lcd_command.linia4.replace("ź","_x");
  174.  
  175. // duże polskie na duże nie polskie
  176. lcd_command.linia1 = lcd_command.linia1.replace("Ń","N");
  177. lcd_command.linia2 = lcd_command.linia2.replace("Ń","N");
  178. lcd_command.linia3 = lcd_command.linia3.replace("Ń","N");
  179. lcd_command.linia4 = lcd_command.linia4.replace("Ń","N");
  180.  
  181. lcd_command.linia1 = lcd_command.linia1.replace("Ą","A");
  182. lcd_command.linia2 = lcd_command.linia2.replace("Ą","A");
  183. lcd_command.linia3 = lcd_command.linia3.replace("Ą","A");
  184. lcd_command.linia4 = lcd_command.linia4.replace("Ą","A");
  185.  
  186. lcd_command.linia1 = lcd_command.linia1.replace("Ć","C");
  187. lcd_command.linia2 = lcd_command.linia2.replace("Ć","C");
  188. lcd_command.linia3 = lcd_command.linia3.replace("Ć","C");
  189. lcd_command.linia4 = lcd_command.linia4.replace("Ć","C");
  190.  
  191. lcd_command.linia1 = lcd_command.linia1.replace("Ę","E");
  192. lcd_command.linia2 = lcd_command.linia2.replace("Ę","E");
  193. lcd_command.linia3 = lcd_command.linia3.replace("Ę","E");
  194. lcd_command.linia4 = lcd_command.linia4.replace("Ę","E");
  195.  
  196. lcd_command.linia1 = lcd_command.linia1.replace("Ł","L");
  197. lcd_command.linia2 = lcd_command.linia2.replace("Ł","L");
  198. lcd_command.linia3 = lcd_command.linia3.replace("Ł","L");
  199. lcd_command.linia4 = lcd_command.linia4.replace("Ł","L");
  200.  
  201. lcd_command.linia1 = lcd_command.linia1.replace("Ó","O");
  202. lcd_command.linia2 = lcd_command.linia2.replace("Ó","O");
  203. lcd_command.linia3 = lcd_command.linia3.replace("Ó","O");
  204. lcd_command.linia4 = lcd_command.linia4.replace("Ó","O");
  205.  
  206. lcd_command.linia1 = lcd_command.linia1.replace("Ś","S");
  207. lcd_command.linia2 = lcd_command.linia2.replace("Ś","S");
  208. lcd_command.linia3 = lcd_command.linia3.replace("Ś","S");
  209. lcd_command.linia4 = lcd_command.linia4.replace("Ś","S");
  210.  
  211. lcd_command.linia1 = lcd_command.linia1.replace("Ż","Z");
  212. lcd_command.linia2 = lcd_command.linia2.replace("Ż","Z");
  213. lcd_command.linia3 = lcd_command.linia3.replace("Ż","Z");
  214. lcd_command.linia4 = lcd_command.linia4.replace("Ż","Z");
  215.  
  216. lcd_command.linia1 = lcd_command.linia1.replace("Ź","Z");
  217. lcd_command.linia2 = lcd_command.linia2.replace("Ź","Z");
  218. lcd_command.linia3 = lcd_command.linia3.replace("Ź","Z");
  219. lcd_command.linia4 = lcd_command.linia4.replace("Ź","Z");
  220.  
  221. poz = 5; // pozycja, od której zacząć wpisywać do
  222. // bufora dane tekstowe
  223.  
  224.  
  225. if(lcd_command.opcje == OPT_LCD_SEKUNDY || lcd_command.opcje == OPT_LCD_MINUTY){
  226. dl_linia = 0;
  227. tmp = lcd_command.linia1.toLatin1();
  228. for(i = 0; i < tmp.size(); i++){
  229. bufor[poz] = tmp.at(i);
  230. if(bufor.at(poz) != 95)
  231. dl_linia++;
  232. poz++;
  233. }
  234. poz += (20 - dl_linia);
  235.  
  236.  
  237. dl_linia = 0;
  238. tmp.clear();
  239. tmp = lcd_command.linia3.toLatin1();
  240. for(i = 0; i < tmp.size(); i++){
  241. bufor[poz] = tmp.at(i);
  242. if(bufor.at(poz) != 95)
  243. dl_linia++;
  244. poz++;
  245. }
  246. poz += (20 - dl_linia);
  247.  
  248. dl_linia = 0;
  249. tmp.clear();
  250. tmp = lcd_command.linia2.toLatin1();
  251. for(i = 0; i < tmp.size(); i++){
  252. bufor[poz] = tmp.at(i);
  253. if(bufor.at(poz) != 95)
  254. dl_linia++;
  255. poz++;
  256. }
  257. poz += (20 - dl_linia);
  258.  
  259.  
  260. dl_linia = 0;
  261. tmp.clear();
  262. tmp = lcd_command.linia4.toLatin1();
  263. for(i = 0; i < tmp.size(); i++){
  264. bufor[poz] = tmp.at(i);
  265. if(bufor.at(poz) != 95)
  266. dl_linia++;
  267. poz++;
  268. }
  269. poz += (20 - dl_linia);
  270. }
  271. if(lcd_command.opcje == OPT_LCD_TIMER_START){
  272. dl_linia = 0;
  273. tmp = lcd_command.linia1.toLatin1();
  274. for(i = 0; i < tmp.size(); i++){
  275. bufor[poz] = tmp.at(i);
  276. if(bufor.at(poz) != 95)
  277. dl_linia++;
  278. poz++;
  279. }
  280. }
  281.  
  282. bufor[0] = 0x0B; //adres rozgłoszeniowy dla wyświetlacza LCD
  283. bufor[1] = LCD_TEXT;//zwykły text
  284. if(lcd_command.opcje == OPT_LCD_TIMER_START ||
  285. lcd_command.opcje == OPT_LCD_TIMER_STOP ||
  286. lcd_command.opcje == OPT_LCD_CLEAR){
  287. bufor[1] = LCD_TIMER1;
  288. }
  289. bufor[2] = poz - 5; //aktualizacja długości tekstu
  290. bufor[3] = lcd_command.czas;
  291. bufor[4] = lcd_command.opcje;
  292.  
  293. quint8 copySize = bufor.at(2)+5;
  294. QByteArray tmpBuff;
  295. tmpBuff = bufor.left(copySize);
  296.  
  297. this->sendData(tmpBuff, 0x02);
  298. }
  299.  
  300. quint16 RS485v2::crc16_update(quint16 crc, quint8 a)
  301. {
  302. quint8 i;
  303.  
  304. crc ^= a;
  305. for (i = 0; i < 8; ++i) {
  306. if (crc & 1)
  307. crc = (crc >> 1) ^ 0xA001;
  308. else
  309. crc = (crc >> 1);
  310. }
  311. return crc;
  312. }
  313.  
  314. bool RS485v2::isOK_CRC(QByteArray buffer, quint16 crc)
  315. {
  316. quint16 newCrc;
  317. quint8 i;
  318. newCrc = 0xFFFF;
  319. for(i = 2; i < buffer.size(); i++){
  320. newCrc = this->crc16_update(newCrc, (quint8)buffer.at(i));
  321. }
  322. return newCrc == crc;
  323. }
  324.  
  325. quint16 RS485v2::calculateCRC16(QByteArray buffer)
  326. {
  327. quint16 newCrc;
  328. quint8 i;
  329. newCrc = 0xFFFF;
  330. for(i = 0; i < buffer.size(); i++){
  331. newCrc = this->crc16_update(newCrc, (quint8)buffer.at(i));
  332. }
  333. return newCrc;
  334. }
  335.  
  336. void RS485v2::sendData(QByteArray bufor, quint16 addres)
  337. {
  338. // UTWORZENIE BUFORA DO WYSYŁKI
  339. // Header protokołu Duna
  340. QByteArray crcBuf, buffer;
  341. QDataStream ds1(&crcBuf, QIODevice::WriteOnly);
  342. ds1 << (quint8)DATA_TYPE_TIMER_DATA; // dataType
  343. ds1 << (quint16)bufor.size(); // dataSize
  344. ds1 << (quint16)0x00; // srcAddr
  345. ds1 << (quint16)addres; // dstAddr dla 7SEG zawsze 0x01; dla LCD zawsze 0x02
  346. ds1 << (quint32)0x0D42; // serial number
  347. ds1 << (quint16)((0x01 << 8) | 0x00); // firmware ver
  348. ds1.unsetDevice();
  349. crcBuf.append(bufor); // dne zegara
  350.  
  351. QDataStream ds2(&buffer, QIODevice::WriteOnly);
  352. ds2 << (quint32) 0x44756E61; // magic header 'Duna'
  353. ds2 << (quint16)this->calculateCRC16(crcBuf);// CRC16
  354. ds2.unsetDevice();
  355. buffer.append(crcBuf); // data
  356. crcBuf.clear();
  357.  
  358. while(this->rs485Busy){
  359. QCoreApplication::processEvents();
  360. }
  361. rs485Busy = true;
  362.  
  363. if(this->slowDataSend){
  364. Sleeper::msleep(1);
  365. char byte;
  366. for(quint8 i = 0; i < buffer.size(); i++){
  367. byte = buffer[i];
  368. this->serialPort->write(&byte,1);
  369. Sleeper::usleep(500); // WARTOŚĆ KRYTYCZNA - 500us
  370. }
  371. Sleeper::msleep(1);
  372. } else {
  373. this->serialPort->write(buffer,buffer.size());
  374. this->serialPort->flush();
  375. QTimer::singleShot(buffer.size() * 2,this,SLOT(rs485SwitchToRead()));
  376. }
  377. }
  378.  
  379. void RS485v2::onSerialDataAvailable()
  380. {
  381. datagramHeader header;
  382. if (serialPort->bytesAvailable()) {
  383. Sleeper::msleep(10);
  384. globalBuffer.append(serialPort->readAll());
  385. }
  386. // jeśli globalBuffer jest większy niż 100 i foundDunaHeader == true
  387. // coś poszło nie tak
  388. if(globalBuffer.size() > 100 && this->foundDunaHeader){
  389. this->foundDunaHeader = false;
  390. }
  391.  
  392. // wykrywamy początek transmisji (magic header == 'Duna')
  393. if(!this->foundDunaHeader){
  394. while ( globalBuffer.size() > 3 && globalBuffer.at(0) != 'D' && globalBuffer.at(0) != 'u' && globalBuffer.at(0) != 'n' && globalBuffer.at(0) != 'a') {
  395. if(globalBuffer.size() > 3){
  396. globalBuffer.remove(0,1);
  397. }
  398. }
  399. }
  400. if(globalBuffer.size() > 3){
  401. // znaleziony header
  402. if(!this->foundDunaHeader){
  403. globalBuffer.remove(0,4);
  404. }
  405. this->foundDunaHeader = true;
  406. } else {
  407. // wycieliśmy początkową sieczkę, ale nie znaleziono nagłowka
  408. return;
  409. }
  410. if( globalBuffer.size() >= DATAGRAM_HEADER_SIZE) {
  411. QByteArray buffer;
  412. buffer = globalBuffer.left(DATAGRAM_HEADER_SIZE);
  413.  
  414. QDataStream stream(buffer);
  415. stream.setByteOrder(QDataStream::LittleEndian);
  416. stream >> header.crc16;
  417. stream >> header.dataType;
  418. stream >> header.dataSize;
  419. stream >> header.srcAddr;
  420. stream >> header.dstAddr;
  421. stream >> header.serialNumber;
  422. stream >> header.firmwareVer;
  423. stream.unsetDevice();
  424. buffer.clear();
  425.  
  426. if((quint32)globalBuffer.size() < (header.dataSize + (quint32)(DATAGRAM_HEADER_SIZE))){
  427. // nie dotarły wszystkie dane, czekamy dalej
  428. return;
  429. }
  430.  
  431. // jeśli program dotarł do tego miejsca, znaczy że dane dotarły wszystkie
  432. globalBuffer.remove(0,DATAGRAM_HEADER_SIZE); // obcięcie headera z bufora
  433. this->foundDunaHeader = false; // znacznik headera już nie potrzebny
  434.  
  435. if(header.dstAddr == 0x00){
  436. // pakiet dla nas (jeśli nie, ignorujemy dane)
  437.  
  438. // TUTAJ SPRAWDZIĆ CRC16!!!!
  439. QByteArray crcBuf;
  440. QDataStream ds(&crcBuf, QIODevice::WriteOnly);
  441. ds.setByteOrder(QDataStream::LittleEndian);
  442. ds << (quint16) header.crc16;
  443. ds << (quint8) header.dataType;
  444. ds << (quint16) header.dataSize;
  445. ds << (quint16) header.srcAddr;
  446. ds << (quint16) header.dstAddr;
  447. ds << (quint32) header.serialNumber;
  448. ds << (quint16) header.firmwareVer;
  449. ds.unsetDevice();
  450. crcBuf.append(globalBuffer.left(header.dataSize));
  451. if(!this->isOK_CRC(crcBuf, header.crc16)){
  452. // PROBLEM!!!!!
  453. // przekłamanie danych
  454. qDebug() << "CRC ERROR!!!!\nModule hwID: "<< header.srcAddr << " SN: "<< header.serialNumber << " FV: "<< header.firmwareVer;
  455. this->foundDunaHeader = false;
  456. globalBuffer.clear();
  457. return;
  458. }
  459.  
  460.  
  461. // #####################################################################
  462. // ##### DANE DOTARŁY ##################################################
  463. // ##### CO TO JEST ZA PAKIET? #########################################
  464. // #####################################################################
  465. if(header.dataType == DATA_TYPE_ACK){
  466. // potwierdzenie odebrania danych
  467. QByteArray datagram;
  468. datagram = globalBuffer.left(header.dataSize);
  469. globalBuffer.remove(0, header.dataSize);
  470. if(header.srcAddr == 0x02){
  471. // potwierdzenie od LCD
  472. emit this->sigLCDAck(datagram);
  473. }
  474. return;
  475. } // header.dataType == DATA_TYPE_ACK
  476.  
  477. // #####################################################################
  478. // ##### DANE DOTARŁY ##################################################
  479. // ##### CO TO JEST ZA PAKIET? #########################################
  480. // #####################################################################
  481. if(header.dataType == DATA_TYPE_TIMER_DATA){
  482. // potwierdzenie odebrania danych
  483. QByteArray datagram;
  484. datagram = globalBuffer.left(header.dataSize);
  485. globalBuffer.remove(0, header.dataSize);
  486. if(header.srcAddr == 0x02){
  487. // klawisz od LCD
  488. emit this->sigLCDKey(datagram);
  489. }
  490. return;
  491. } // header.dataType == DATA_TYPE_TIMER_DATA
  492.  
  493. } else { // header.dstAddr == 0x00
  494. globalBuffer.remove(0,header.dataSize);
  495. }
  496.  
  497. }
  498. }
Advertisement
Add Comment
Please, Sign In to add comment