1 // Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the
14 // * All advertising materials mentioning features or use of this
15 // software must display the following acknowledgement: This product
16 // includes software developed by tm3d.de and its contributors.
17 // * Neither the name of tm3d.de nor the names of its contributors may
18 // be used to endorse or promote products derived from this software
19 // without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include "mySensorDB.h"
54 #include <fcntl.h> /* For O_RDWR */
65 #define RB "\e(0\x6a\e(B" // 188 Right Bottom corner
66 #define RT "\e(0\x6b\e(B" // 187 Right Top corner
67 #define LT "\e(0\x6c\e(B" // 201 Left Top cornet
68 #define LB "\e(0\x6d\e(B" // 200 Left Bottom corner
69 #define MC "\e(0\x6e\e(B" // 206 Midle Cross
70 #define HL "\e(0\x71\e(B" // 205 Horizontal Line
71 #define LC "\e(0\x74\e(B" // 204 Left Cross
72 #define RC "\e(0\x75\e(B" // 185 Right Cross
73 #define BC "\e(0\x76\e(B" // 202 Bottom Cross
74 #define TC "\e(0\x77\e(B" // 203 Top Cross
75 #define VL "\e(0\x78\e(B" // 186 Vertical Line
76 #define SP " " // space string
77 #define BLUE_B "\033[1;34m"
78 #define COLOR_E "\033[0m"
79 #define C2_B "\033[0;36m"
80 #define C3_B "\033[3;34m"
81 #define C4_B "\033[1;33m"
82 #define C5_B "\033[4;33m"
85 #define RB " "// 188 Right Bottom corner
86 #define RT " "// 187 Right Top corner
87 #define LT " "// 201 Left Top cornet
88 #define LB " "// 200 Left Bottom corner
89 #define MC " " // 206 Midle Cross
90 #define HL " "// 205 Horizontal Line
91 #define LC " "// 204 Left Cross
92 #define RC " "// 185 Right Cross
93 #define BC " "// 202 Bottom Cross
94 #define TC " "// 203 Top Cross
95 #define VL " "// 186 Vertical Line
96 #define SP " " // space string
108 printf("owTools - Program for reading and controlling 1-Wire Devices from www.tm3d.de\n\n");
109 printf("run: owTools -a [COMn|USBn|GPIOn] [options]\n\n");
110 printf(" COMn -> Adapter DS9097 and compatible (e.g. LinkUSB)\n");
111 printf(" n=1 -> Windows COM1 -> Linux /dev/ttyS1\n");
112 printf(" USBn -> Adapter DS2490/DS9490 \n");
113 printf(" n=1 -> first USB-Adapter \n");
114 printf(" GPIOn -> port of RaspberrPI (port Name not Pin number)\n\n");
115 printf("Options:\n");
116 printf(" -i interactive mode\n");
117 printf(" select a device and get information about it\n");
118 printf(" -s \"id as 64bit Hex\" try to skip select menu with this id \n");
119 printf(" example: -s \"5D02160084D9A220\" \n");
120 printf(" -c read and print all continuous\n");
121 printf(" -p time in sec between readings\n");
122 printf(" -d [config file] put all Data in mysql Database descripted in config file\n");
123 printf(" Config file: \n");
124 printf(" [server]\n");
125 printf(" [port] -> 3306\n");
126 printf(" [user] \n");
127 printf(" [password]\n");
128 printf(" [database]\n");
129 printf(" [prefix] -> a prefix of all tables \n\n");
130 printf(" -r Search every time for new Devices\n");
131 printf(" -t [text_file] append comma separadet to text-file\n");
132 printf(" -j Use 0xCC 0x44 to send convert temperature to all DS18B20 and DS2438\n");
133 printf(" -f [hexfile] flash new\n");
134 printf(" -n [\"id as 64bit Hex\"] change id \n");
135 printf(" example: -n \"5D02160084D9A220\" \n");
136 printf(" no argument increments id by 256 (keep family code) \n");
137 printf(" -g get from server\n");
138 printf(" -w [1|2] show Warnings (1) or all information (2)\n");
139 printf(" -m memory functions\n");
140 printf(" -x write direct 1-Wire\n");
154 //length of shown chars of an UTF8 string ... sometimes not the same as byte count
155 std::size_t utf8_length(std::string const &s) {
157 std::string::const_iterator begin = s.begin(), end = s.end();
158 while (begin != end) {
159 unsigned char c = *begin;
161 if ((c & 0x80) == 0) n = 1;
162 else if ((c & 0xE0) == 0xC0) n = 2;
163 else if ((c & 0xF0) == 0xE0) n = 3;
164 else if ((c & 0xF8) == 0xF0) n = 4;
173 std::vector<arg_t> comlist;
175 std::string getArg(std::string flag) {
176 for(arg_t a:comlist) {
177 if (a.flag==flag) return a.arg;
184 int getArgi(std::string flag) {
185 return atoi(getArg(flag).c_str());
190 mySensorDB *sdb=NULL;
193 std::string textfilename;
197 snum_t getArgsnum(std::string flag) {
203 int findCPU(std::string cpu) {
204 std::ifstream fileInput;
206 fileInput.open("/proc/cpuinfo");
207 if(fileInput.is_open()) {
208 for(unsigned int curLine = 0; getline(fileInput, line); curLine++) {
209 if (line.find(cpu) != std::string::npos) {
223 owInterface *owi= NULL;
226 if (getArg("w")=="2")
227 owi->log->setLogLevel(0);
228 else if (getArg("w")=="2") owi->log->setLogLevel(0);
229 else owi->log->setLogLevel(OWLOG_ERROR);
233 int appendTextFile(std::string line) {
235 file.open(textfilename, std::ios::out | std::ios::app);
237 owi->log->set(OWLOG_ERROR,"Can not open outputfile for text output");
242 file << line << std::endl;
248 void continuous(std::vector<owDevice*> *devices,int intervall,int headline,int searchrom) {
256 if (owi->isDevicesChanged()||(first==1)) {
260 for (owDevice* dev :*devices) {
261 if (dev->configstate!=OWDCS_NONE) {
262 for (size_t i=0;i<4;i++) {
263 if (dev->config->getPropertyID((uint8_t)i)!=0)
264 printf(BLUE_B "%02X.%02X%02X" COLOR_E "\t",dev->getNum().byte[7],dev->getNum().byte[1],dev->getNum().byte[0]);
269 for (owDevice* dev :*devices) {
270 if (dev->configstate!=OWDCS_NONE) {
271 for (size_t i=0;i<4;i++) {
272 if (dev->config->getPropertyID((uint8_t)i)!=0)
273 printf(C2_B "%s" COLOR_E "\t",dev->config->getQuantity((uint8_t)i).substr(0,7).c_str());
278 for (owDevice* dev :*devices) {
279 if (dev->configstate!=OWDCS_NONE) {
280 for (size_t i=0;i<4;i++) {
281 if (dev->config->getPropertyID((uint8_t)i)!=0) {
282 size_t l=utf8_length(dev->config->getUnit((uint8_t)i));
284 printf(C3_B "[%s]%s" COLOR_E "\t",dev->config->getUnit((uint8_t)i).c_str(),ls.substr(0,5-l).c_str());
294 //owi->log->setLogLevel(0);
295 for (owDevice* dev : *devices) {
296 sdb->createDeviceTable(dev);
306 struct tm tm = *localtime(&t);
313 printf("%d-%02d-%02d %02d:%02d:%02d\t", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
315 snprintf(valbuf,100,"%d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
320 for (owDevice* dev :*devices) {
321 for(int k=0;k<owi->maxrepeat;k++){
322 if (owCC_44_Temp>0) {
323 std::vector<uint8_t> data;
324 data.push_back(0xCC);
325 data.push_back(0x44);
327 owi->Communicate(&data, 2, 0);
330 if (owi->log->last()<OWLOG_ERROR) break;
333 if (owi->log->last()<OWLOG_ERROR) {
334 if (dev->configstate!=OWDCS_NONE) {
335 for (size_t i=0;i<4;i++) {
336 if (dev->config->getPropertyID((int8_t)i)!=0) {
337 if (dev->values[i]<=-10)
338 printf("%0.2f \t",dev->values[i]);
339 else if (dev->values[i]<0)
340 printf("%0.3f \t",dev->values[i]);
341 else if (dev->values[i]<10)
342 printf("%0.4f \t",dev->values[i]);
343 else if (dev->values[i]<100)
344 printf("%0.3f \t",dev->values[i]);
345 else if (dev->values[i]<1000)
346 printf("%0.2f \t",dev->values[i]);
348 printf("%0.1f \t",dev->values[i]);
351 snprintf(valbuf,100,",%0.4f",dev->values[i]);
359 sdb->insertValues(dev);
363 owi->log->setLogLevel(OWLOG_INFO);
364 owi->log->set(OWLOG_ERROR,"Too many errors, mybee conection is dead.");
374 while (((int)time(NULL)) < (st + intervall)) {
385 void device_menu(owDevice* d) {
386 for(int i=0;i<70;i++) printf(HL);printf("\n");
387 printf("Selected Device: ");
388 snum_t snum=d->getNum();
389 printf(BLUE_B "%016llX" COLOR_E,(unsigned long long)snum.num);
391 printf("Chip Info: ");
392 std::vector<std::string> info=d->getFamilyInfo();
393 for (std::string s : info) printf(" %s",s.c_str());
395 printf("Values info: ");
396 int tm3d=d->readConfig();
397 for (size_t i=0;i<4;i++) {
398 printf("%s in %s",d->config->getQuantity((uint8_t)i).c_str(),d->config->getUnit((uint8_t)i).c_str());
399 if (i<4) printf("; ");
401 if (tm3d) printf(" (tm3d.de)"); else printf(" (default)");
404 for (size_t i=0;i<d->values.size();i++) {
405 printf(C4_B "%0.4f %s" COLOR_E,d->values[i],d->config->getUnit((uint8_t)i).c_str());
408 for(int i=0;i<70;i++) printf(HL);printf("\n");
410 printf("1) Run continuous\n");
413 printf("Select an option: ");std::getline (std::cin,inp);
414 int dnr=atoi(inp.c_str());
417 std::vector<owDevice*> v;
419 continuous(&v,1,1,0);
421 // if (dnr<=i) break;
422 // printf("\033[4;33mSelect a number between 0 and %i\033[0m\n",i);
433 unsigned long long l = 0;
434 if ((s = getArg("s")) != "") {
435 l = strtoull(s.c_str(), &end, 16);
436 for (owDevice* dev : owi->devices) {
438 snum_t snum = dev->getNum();
439 if (l == snum.num) return i;
442 printf("Number not found -> Select one or exit!\n");
446 for (owDevice* dev :owi->devices) {
448 snum_t snum=dev->getNum();
450 printf(BLUE_B "%016llX" COLOR_E,(unsigned long long)snum.num);
453 for (int j=0;j<4;j++) printf("%s ",dev->config->getQuantity(j).c_str());
456 printf("0) Exit Programm\n");
460 printf("Select device with number: ");std::getline (std::cin,inp);
461 dnr=atoi(inp.c_str());
462 if (dnr<=0) return 0;
464 printf(C5_B "Select a number between 0 and %i" COLOR_E "\n",i);
470 int questionYesNo(std::string text) {
472 printf("%s [Y/n] ",text.c_str());std::getline (std::cin,inp);
473 if (inp=="Y") return 1; else return 0;
477 void interactive(owInterface *owi) {
479 int i=selectDevice();
481 device_menu(owi->devices[i-1]);
485 int main(int argc, char *argv[]) {
488 //printf("Kommando: %s:\n", argv[0]);
490 if (**++argv != '-') {
491 //printf(" Arg. = %s\n", *argv);
492 if (comlist.empty()) {
495 comlist.push_back(a);
497 if ((*(comlist.end()-1)).arg!="1") {
500 comlist.push_back(a);
502 (*(comlist.end()-1)).arg=*argv;
506 for( i=1; (*argv)[i] != '\0'; i++) {
507 //printf(" Flag = (%c)\n", (*argv)[i]);
510 comlist.push_back(a);
515 //for(arg_t a:comlist) printf("%s->%s\n",a.flag.c_str(),a.arg.c_str());
516 if (getArg("h")=="1") {
520 std::string adapter=getArg("a");
521 if (adapter.empty()) {
525 std::transform(adapter.begin(), adapter.end(),adapter.begin(), ::toupper);
529 if(adapter.find("COM")!=std::string::npos) {
530 owi=new owCOMInterface();
531 int port=atoi(adapter.substr(adapter.find("COM")+3).c_str());
532 printf("Open /dev/ttyUSB%i\n",port);
533 owi->InitAdapter(port);
535 if(adapter.find("USB")!=std::string::npos) {
536 owi=new owUSBInterface();
537 int port=atoi(adapter.substr(adapter.find("USB")+3).c_str());
538 printf("Open the %i. USB Adapter\n",port);
540 if ((err=owi->InitAdapter(port))<0) {
541 if (err==-1) printf("No Adapter found!\n On Linux, try: sudo owTools....\n On Windows: Install libusb0 driver\n");
542 if (err==-2) printf("Maybe Adapter is used ... (try sudo)\nOn Linux: If the kernel modul is loaded type: sudo rmmod ds2490\n");
546 if(adapter.find("GPIO")!=std::string::npos) {
547 if (findCPU("BCM2708")) {
548 printf("\033[1;33mRaspberry Pi 1 is dedected. 1-wire on the GPIO port can have many errors in the transfer.\033[0m\n");
549 owi=new owPiGPioInterface();
550 int port=atoi(adapter.substr(adapter.find("GPIO")+4).c_str());
551 printf("Open GPIO %i\n",port);
552 } else if (findCPU("BCM2709")) {
553 owi=new owPiGPioInterface();
554 int port=atoi(adapter.substr(adapter.find("GPIO")+4).c_str());
555 printf("Open GPIO %i\n",port);
556 owi->InitAdapter(port);
558 printf("\033[1;31mGPIO works with Raspberry PI only \033[0m\n");
561 if(adapter.find("W1")!=std::string::npos) {
562 owi=new owW1Interface();
563 if (owi->InitAdapter(0)) {
564 printf("Use W1-Kernel 1-Wire functions on /sys/bus/w1\n");
565 } else printf("No W1-Kernel module found!!\n");
568 if (adapter.find("ARDUINO") != std::string::npos) {
569 owi = new owARDUINOInterface();
570 int port = atoi(adapter.substr(adapter.find("ARDUINO") + 7).c_str());
571 printf("Open /dev/ttyS%i\n", port);
572 owi->InitAdapter(port);
577 if (adapter.find("USB") != std::string::npos) {
579 owi = new owTMEXWIN();
580 int port = atoi(adapter.substr(adapter.find("USB") + 3).c_str());
581 printf("Open the %i. USB Adapter\n", port);
584 sprintf_s(cs, 20, "{%i,6}", port);
585 if ((err = owi->InitAdapter(cs))==0) {
586 printf("ERROR Init USB Adapter\n");
591 if (adapter.find("COM") != std::string::npos) {
592 owi = new owTMEXWIN();
593 int port = atoi(adapter.substr(adapter.find("COM") + 3).c_str());
594 printf("Open Adapter on COM%i\n", port);
597 sprintf_s(cs, 20, "{%i,5}", port);
598 if ((err = owi->InitAdapter(cs))==0) {
599 printf("ERROR Init Serial Adapter\n");
605 printf("No 1-Wiremaster found\n");
612 if (getArg("i")=="1") {
615 if (getArg("c")=="1") {
616 if (getArg("j")=="1") {
617 printf("Use 1-Wire command 0xCC 0x44 to send convert temperature to all DS18B20 and DS2438\n");
620 int reload=(getArg("r")=="1");
623 //owi->log->setLogLevel(3);
626 if ((s=getArg("p")) !="") {
627 pause=atoi(s.c_str());
630 if ((s=getArg("d")) !="") {
632 printf("Use Database\n");
633 sdb=new mySensorDB(s,owi->log);
634 if (sdb->log->last()>OWLOG_WARNING) {
638 if (sdb->log->last()>OWLOG_WARNING) {
641 sdb->createSensorTable();
642 if (sdb->log->last()>OWLOG_WARNING) {
648 if ((s=getArg("t")) !="") {
650 printf("Write values to textfile %s\n",s.c_str());
654 continuous(&(owi->devices),pause,1,reload);
656 if ((s=getArg("f"))!="") {
657 printf("Flash %s in selected Device\n",s.c_str());
658 int sel=selectDevice();
660 int resetid=questionYesNo("Would you reset to default ID? (This is necessary if another device is used!)");
661 owi->log->setLogLevel(OWLOG_INFO);
662 owi->flashHEXFile(s,owi->device_nums[sel-1],resetid,1);
666 for (owDevice* dev :owi->devices) {
667 snum_t snum=dev->getNum();
668 printf(BLUE_B "%016llX" COLOR_E,(unsigned long long)snum.num);
672 printf("%i Devices found\n",(int)owi->devices.size());
675 if ((s=getArg("v"))!="") {
676 printf("Reset VOC\n");
677 int sel=selectDevice();
679 owDevice* dev=owi->devices[sel-1];
680 std::vector<uint8_t> cl;
685 dev->Communicate(&cl,4,0);
687 //------------------------------------------------------------------------------------------
688 // --------------------- Direct Write
689 //------------------------------------------------------------------------------------------
691 if ((s=getArg("x"))!="") {
692 std::vector<uint8_t> v;
695 for ( std::string::iterator it = s.begin() ; it < s.end(); it++ ,sp++) {
699 if (ts.length()>=2) {
700 v.push_back(strtoul(ts.c_str(),NULL, 16));
705 if (ts.length()!=0) {
706 v.push_back(strtoul(ts.c_str(),NULL, 16));
709 for (uint8_t val :v) printf("%02X ",val);
710 printf(" to selected Device\n");
711 int sel=selectDevice();
714 owDevice* dev=owi->devices[sel];
715 dev->Communicate(&v,v.size(),0);
716 for (uint8_t val :v) printf("%02X ",val);
723 //------------------------------------------------------------------------------------------
724 // --------------------- Memory functions
725 //------------------------------------------------------------------------------------------
727 if ((s=getArg("m"))!="") {
729 std::vector<uint8_t> mem;
730 if(s.find("read")!=std::string::npos) {
731 size_t cla=s.find_first_of("(",0);
732 size_t page=s.find_first_of("p=",cla);
733 size_t epage=s.find_first_of(";",page);
734 if (epage==std::string::npos) epage=s.find_first_of(")",page);
735 std::string pn=s.substr(page+2,epage-page-2);
736 printf("%s Read Memory Page %s of Device:\n",s.c_str(),pn.c_str());
737 pnr=atoi(pn.c_str());
740 if(s.find("write")!=std::string::npos) {
741 size_t cla=s.find("(",0);
742 size_t page=s.find("p=",cla);
743 size_t epage=s.find(";",page);
744 if (epage==std::string::npos) epage=s.find_first_of(")",page);
745 std::string pn=s.substr(page+2,epage-page-2);
746 size_t data=s.find("d=",cla);
747 size_t edata=s.find(";",data);
748 if (edata==std::string::npos) edata=s.find(")",data);
749 std::string pd=s.substr(data+2,edata-data-2);
750 std::istringstream pdss(pd);
751 //std::cout << pd <<std::endl;
752 while (!pdss.eof()) {
758 for(uint8_t v :mem) printf("%02X ",v);
759 printf("to Memory Page %s of Device:\n",pn.c_str());
760 pnr=atoi(pn.c_str());
763 int sel=selectDevice();
766 //snum_t snum=owi->devices[sel]->getNum();
767 owDevice* dev=owi->devices[sel];
768 if(s.find("read")!=std::string::npos) {
769 int r=dev->readMemory(pnr,0,dev->getPageSize(),&mem);
770 for(int i=0;i<r;i++) printf("%02X ",mem[i]);
774 if(s.find("write")!=std::string::npos) {
775 int r=dev->writeMemory(pnr,0,dev->getPageSize(),&mem);
776 r=dev->readMemory(pnr,0,dev->getPageSize(),&mem);
777 for(int i=0;i<r;i++) printf("%02X ",mem[i]);
782 if ((s=getArg("n"))!="") {
783 printf("Change id of selected Device\n");
784 int sel=selectDevice();
788 snum_t snum=owi->devices[sel]->getNum();
790 if ((getArg("g"))=="1") {
791 printf("get ID from Server\n");
794 sprintf(s,"wget -q http://www.tm3d.de/shop99/owid.php?fam=%02X -O id.txt",snum.byte[0]);
797 sprintf_s(s, "wget -q http://www.tm3d.de/shop99/owid.php?fam=%02X -O id.txt", snum.byte[0]);
800 if ((err=system(s))==0) {
803 std::stringstream str;
809 while(fs.peek() != EOF) {
810 char c= (char) fs.get();
814 if ((c==',')|(c=='}')) {
815 isnum.byte[i]=(uint8_t)strtoull(s, NULL, 16);
816 //printf("%x\n",strtol(s, NULL, 16));
832 } else (printf("ERROR %i\n",err));
837 unsigned long long l=strtoull(s.c_str(),NULL,16);
838 if ((snum.num&0xFF)!=(l&0xFF)) {
839 printf("This command change family-fode of Device 0x%02X->0x%02X\n",(int)(snum.num&0xFF),(int)(l&0xFF));
840 int resetid=questionYesNo("Are you sure?");
842 printf("ERROR: Family of Device 0x%02X->0x%02X can not be changed\n",(int)(snum.num&0xFF),(int)(l&0xFF));
847 //printf("->%016llX\n",(unsigned long long)l);
854 printf(BLUE_B "%016llX" COLOR_E,(unsigned long long)snum.num);
858 owi->devices[sel]->changeID(snum);
862 for (owDevice* dev :owi->devices) {
863 snum_t snum=dev->getNum();
864 printf(BLUE_B "%016llX" COLOR_E,(unsigned long long)snum.num);
868 printf("%i Devices found\n",(int)owi->devices.size());
872 for (owDevice* dev :owi->devices) {
873 printf("_______________________________________________________________________\n");
874 snum_t snum=dev->getNum();
875 printf(BLUE_B "%016llX " COLOR_E,(unsigned long long)snum.num);
876 switch (dev->configstate) {
877 case OWDCS_16:printf("old Configcode from www.tm3d.de");break;
878 case OWDCS_24:printf("Configcode from www.tm3d.de");break;
879 case OWDCS_DEFAULT:printf("Default Configcode set by this Software");break;
880 case OWDCS_NONE:printf("No Configcode");break;
884 printf(" %s",dev->getFamilyInfo()[i].c_str());
886 if (dev->configstate!=OWDCS_NONE) {
887 std::vector<std::vector<std::string>> ia;
888 std::vector<size_t> maxcol;
890 for(int i=0;i<4;i++) {
891 std::vector<std::string> colm;
893 colm.push_back(dev->config->getSensorChip(i));
894 if (max<utf8_length(colm[0])) max=utf8_length(colm[0]);
895 colm.push_back(dev->config->getQuantity(i));
896 if (max<utf8_length(colm[1])) max=utf8_length(colm[1]);
897 colm.push_back(dev->config->getUnit(i));
898 if (max<utf8_length(colm[2])) max=utf8_length(colm[2]);
899 if (dev->config->getPropertyID(i)==0) {
904 sprintf(hs,"%0.3f",dev->values[i]);
907 sprintf_s(hs, "%0.3f", dev->values[i]);
911 if (max<utf8_length(colm[3])) max=utf8_length(colm[3]);
913 maxcol.push_back(max);
915 std::string space=" ";
916 for(int i=0;i<4;i++) {
917 for(int j=0;j<4;j++) {
918 printf("%s%s",ia[j][i].c_str(),space.substr(0,maxcol[j]-utf8_length(ia[j][i])+2).c_str());
924 printf("%i Devices found\n",(int)owi->devices.size());