_loraFiles.ino 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. // 1-channel LoRa Gateway for ESP8266
  2. // Copyright (c) 2016, 2017, 2018, 2019 Maarten Westenberg version for ESP8266
  3. // Version 6.1.5
  4. // Date: 2019-12-20
  5. //
  6. // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
  7. // and many others.
  8. //
  9. // All rights reserved. This program and the accompanying materials
  10. // are made available under the terms of the MIT License
  11. // which accompanies this distribution, and is available at
  12. // https://opensource.org/licenses/mit-license.php
  13. //
  14. // NO WARRANTY OF ANY KIND IS PROVIDED
  15. //
  16. // Author: Maarten Westenberg (mw12554@hotmail.com)
  17. //
  18. // This file contains the LoRa filesystem specific code
  19. #if _MONITOR>=1
  20. // ----------------------------------------------------------------------------
  21. // LoRa Monitor logging code.
  22. // Define one print function and depending on the loggin parameter output
  23. // to _USB of to the www screen function
  24. // ----------------------------------------------------------------------------
  25. int initMonitor(struct moniLine *monitor) {
  26. for (int i=0; i< _MONITOR; i++) {
  27. //monitor[i].txt[0]=0;
  28. monitor[i].txt="";
  29. }
  30. return(1);
  31. }
  32. #endif //_MONITOR
  33. // ============================================================================
  34. // LORA SPIFFS FILESYSTEM FUNCTIONS
  35. //
  36. // The LoRa supporting functions are in the section below
  37. // ----------------------------------------------------------------------------
  38. // Supporting function to readConfig
  39. // ----------------------------------------------------------------------------
  40. void id_print (String id, String val) {
  41. #if _DUSB>=1
  42. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  43. Serial.print(id);
  44. Serial.print(F("=\t"));
  45. Serial.println(val);
  46. }
  47. #endif //_DUSB
  48. }
  49. // ----------------------------------------------------------------------------
  50. // INITCONFIG; Init the gateway configuration file
  51. // Espcecially when calling SPIFFS.format() the gateway is left in an init
  52. // which is not very well defined. This function will init some of the settings
  53. // to well known settings.
  54. // ----------------------------------------------------------------------------
  55. int initConfig(struct espGwayConfig *c) {
  56. (*c).ch = 0;
  57. (*c).sf = _SPREADING;
  58. (*c).debug = 1;
  59. (*c).pdebug = P_GUI;
  60. (*c).cad = _CAD;
  61. (*c).hop = false;
  62. (*c).seen = false;
  63. (*c).expert = false;
  64. (*c).monitor = false;
  65. (*c).txDelay = 0; // First Value without saving is 0;
  66. (*c).trusted = 1;
  67. }
  68. // ----------------------------------------------------------------------------
  69. // Read the gateway configuration file
  70. // ----------------------------------------------------------------------------
  71. int readConfig(const char *fn, struct espGwayConfig *c) {
  72. int tries = 0;
  73. #if _DUSB>=1
  74. Serial.println(F("readConfig:: Starting "));
  75. #endif //_DUSB
  76. if (!SPIFFS.exists(fn)) {
  77. #if _DUSB>=1
  78. Serial.print(F("readConfig ERR:: file="));
  79. Serial.print(fn);
  80. Serial.println(F(" does not exist .. Formatting"));
  81. #endif //_DUSB
  82. SPIFFS.format();
  83. initConfig(c); // If we cannot read teh config, at least init known values
  84. return(-1);
  85. }
  86. File f = SPIFFS.open(fn, "r");
  87. if (!f) {
  88. #if _DUSB>=1
  89. Serial.println(F("ERROR:: SPIFFS open failed"));
  90. #endif //_DUSB
  91. return(-1);
  92. }
  93. while (f.available()) {
  94. #if _DUSB>=1
  95. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  96. Serial.print('.');
  97. }
  98. #endif //_DUSB
  99. // If we wait for more than 10 times, reformat the filesystem
  100. // We do this so that the system will be responsive (over OTA for example).
  101. //
  102. if (tries >= 10) {
  103. f.close();
  104. #if _DUSB>=1
  105. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  106. Serial.println(F("Formatting"));
  107. }
  108. #endif //_DUSB
  109. SPIFFS.format();
  110. initConfig(c);
  111. f = SPIFFS.open(fn, "r");
  112. tries = 0;
  113. }
  114. String id =f.readStringUntil('='); // Read keyword until '=', C++ thing
  115. String val=f.readStringUntil('\n'); // Read value until End of Line (EOL)
  116. #if _DUSB>=2
  117. Serial.print(F("readConfig:: reading line="));
  118. Serial.print(id);
  119. Serial.print(F("="));
  120. Serial.print(val);
  121. Serial.println();
  122. #endif //_DUSB
  123. if (id == "SSID") { // WiFi SSID
  124. id_print(id, val);
  125. (*c).ssid = val; // val contains ssid, we do NO check
  126. }
  127. else if (id == "PASS") { // WiFi Password
  128. id_print(id, val);
  129. (*c).pass = val;
  130. }
  131. else if (id == "CH") { // Frequency Channel
  132. id_print(id,val);
  133. (*c).ch = (uint32_t) val.toInt();
  134. }
  135. else if (id == "SF") { // Spreading Factor
  136. id_print(id, val);
  137. (*c).sf = (uint32_t) val.toInt();
  138. }
  139. else if (id == "FCNT") { // Frame Counter
  140. id_print(id, val);
  141. (*c).fcnt = (uint32_t) val.toInt();
  142. }
  143. else if (id == "DEBUG") { // Debug Level
  144. id_print(id, val);
  145. (*c).debug = (uint8_t) val.toInt();
  146. }
  147. else if (id == "PDEBUG") { // pDebug Pattern
  148. id_print(id, val);
  149. (*c).pdebug = (uint8_t) val.toInt();
  150. }
  151. else if (id == "CAD") { // CAD setting
  152. id_print(id, val);
  153. (*c).cad = (uint8_t) val.toInt();
  154. }
  155. else if (id == "HOP") { // HOP setting
  156. id_print(id, val);
  157. (*c).hop = (uint8_t) val.toInt();
  158. }
  159. else if (id == "BOOTS") { // BOOTS setting
  160. id_print(id, val);
  161. (*c).boots = (uint8_t) val.toInt();
  162. }
  163. else if (id == "RESETS") { // RESET setting
  164. id_print(id, val);
  165. (*c).resets = (uint8_t) val.toInt();
  166. }
  167. else if (id == "WIFIS") { // WIFIS setting
  168. id_print(id, val);
  169. (*c).wifis = (uint8_t) val.toInt();
  170. }
  171. else if (id == "VIEWS") { // VIEWS setting
  172. id_print(id, val);
  173. (*c).views = (uint8_t) val.toInt();
  174. }
  175. else if (id == "NODE") { // NODE setting
  176. id_print(id, val);
  177. (*c).isNode = (uint8_t) val.toInt();
  178. }
  179. else if (id == "REFR") { // REFR setting
  180. id_print(id, val);
  181. (*c).refresh = (uint8_t) val.toInt();
  182. }
  183. else if (id == "REENTS") { // REENTS setting
  184. id_print(id, val);
  185. (*c).reents = (uint8_t) val.toInt();
  186. }
  187. else if (id == "NTPERR") { // NTPERR setting
  188. id_print(id, val);
  189. (*c).ntpErr = (uint8_t) val.toInt();
  190. }
  191. else if (id == "NTPETIM") { // NTPERR setting
  192. id_print(id, val);
  193. (*c).ntpErrTime = (uint32_t) val.toInt();
  194. }
  195. else if (id == "NTPS") { // NTPS setting
  196. id_print(id, val);
  197. (*c).ntps = (uint8_t) val.toInt();
  198. }
  199. else if (id == "FILENO") { // FILENO setting
  200. id_print(id, val);
  201. (*c).logFileNo = (uint8_t) val.toInt();
  202. }
  203. else if (id == "FILEREC") { // FILEREC setting
  204. id_print(id, val);
  205. (*c).logFileRec = (uint16_t) val.toInt();
  206. }
  207. else if (id == "FILENUM") { // FILEREC setting
  208. id_print(id, val);
  209. (*c).logFileNum = (uint16_t) val.toInt();
  210. }
  211. else if (id == "EXPERT") { // EXPERT button setting
  212. id_print(id, val);
  213. (*c).expert = (uint8_t) val.toInt();
  214. }
  215. else if (id == "SEEN") { // SEEN button setting
  216. id_print(id, val);
  217. (*c).seen = (uint8_t) val.toInt();
  218. }
  219. else if (id == "MONITOR") { // MONITOR button setting
  220. id_print(id, val);
  221. (*c).monitor = (uint8_t) val.toInt();
  222. }
  223. else if (id == "DELAY") { // DELAY setting
  224. id_print(id, val);
  225. (*c).txDelay = (int32_t) val.toInt();
  226. }
  227. else if (id == "TRUSTED") { // TRUSTED setting
  228. id_print(id, val);
  229. (*c).trusted= (int32_t) val.toInt();
  230. }
  231. else {
  232. #if _DUSB>=1
  233. Serial.print(F("readConfig:: tries++"));
  234. #endif //_DUSB
  235. tries++;
  236. }
  237. }
  238. f.close();
  239. #if _DUSB>=1
  240. if (debug>=1) {
  241. Serial.println(F("readConfig:: Fini"));
  242. }
  243. Serial.println();
  244. #endif //_DUSB
  245. return(1);
  246. }//readConfig
  247. // ----------------------------------------------------------------------------
  248. // Write the current gateway configuration to SPIFFS. First copy all the
  249. // separate data items to the gwayConfig structure
  250. //
  251. // Note: gwayConfig.expert contains the expert setting already
  252. // gwayConfig.txDelay
  253. // ----------------------------------------------------------------------------
  254. int writeGwayCfg(const char *fn) {
  255. gwayConfig.ssid = WiFi.SSID();
  256. gwayConfig.pass = WiFi.psk(); // XXX We should find a way to store the password too
  257. gwayConfig.ch = ifreq; // Frequency Index
  258. gwayConfig.sf = (uint8_t) sf; // Spreading Factor
  259. gwayConfig.debug = debug;
  260. gwayConfig.pdebug = pdebug;
  261. gwayConfig.cad = _cad;
  262. gwayConfig.hop = _hop;
  263. #if GATEWAYNODE==1
  264. gwayConfig.fcnt = frameCount;
  265. #endif //GATEWAYNODE
  266. return(writeConfig(fn, &gwayConfig));
  267. }
  268. // ----------------------------------------------------------------------------
  269. // Write the configuration as found in the espGwayConfig structure
  270. // to SPIFFS
  271. // Parameters:
  272. // fn; Filename
  273. // c; struct config
  274. // Returns:
  275. // 1 when successful, -1 on error
  276. // ----------------------------------------------------------------------------
  277. int writeConfig(const char *fn, struct espGwayConfig *c) {
  278. // Assuming the cibfug file is the first we write...
  279. // If it is not there we should format first.
  280. // NOTE: Do not format for other files!
  281. if (!SPIFFS.exists(fn)) {
  282. #if _DUSB>=1
  283. Serial.print("WARNING:: writeConfig, file not exists, formatting ");
  284. #endif //_DUSB
  285. SPIFFS.format();
  286. initConfig(c); // XXX make all initial declarations here if config vars need to have a value
  287. #if _DUSB>=1
  288. Serial.println(fn);
  289. #endif //_DUSB
  290. }
  291. File f = SPIFFS.open(fn, "w");
  292. if (!f) {
  293. #if _DUSB>=1
  294. Serial.print("writeConfig: ERROR open file=");
  295. Serial.print(fn);
  296. Serial.println();
  297. #endif //_DUSB
  298. return(-1);
  299. }
  300. f.print("SSID"); f.print('='); f.print((*c).ssid); f.print('\n');
  301. f.print("PASS"); f.print('='); f.print((*c).pass); f.print('\n');
  302. f.print("CH"); f.print('='); f.print((*c).ch); f.print('\n');
  303. f.print("SF"); f.print('='); f.print((*c).sf); f.print('\n');
  304. f.print("FCNT"); f.print('='); f.print((*c).fcnt); f.print('\n');
  305. f.print("DEBUG"); f.print('='); f.print((*c).debug); f.print('\n');
  306. f.print("PDEBUG"); f.print('='); f.print((*c).pdebug); f.print('\n');
  307. f.print("CAD"); f.print('='); f.print((*c).cad); f.print('\n');
  308. f.print("HOP"); f.print('='); f.print((*c).hop); f.print('\n');
  309. f.print("NODE"); f.print('='); f.print((*c).isNode); f.print('\n');
  310. f.print("BOOTS"); f.print('='); f.print((*c).boots); f.print('\n');
  311. f.print("RESETS"); f.print('='); f.print((*c).resets); f.print('\n');
  312. f.print("WIFIS"); f.print('='); f.print((*c).wifis); f.print('\n');
  313. f.print("VIEWS"); f.print('='); f.print((*c).views); f.print('\n');
  314. f.print("REFR"); f.print('='); f.print((*c).refresh); f.print('\n');
  315. f.print("REENTS"); f.print('='); f.print((*c).reents); f.print('\n');
  316. f.print("NTPETIM"); f.print('='); f.print((*c).ntpErrTime); f.print('\n');
  317. f.print("NTPERR"); f.print('='); f.print((*c).ntpErr); f.print('\n');
  318. f.print("NTPS"); f.print('='); f.print((*c).ntps); f.print('\n');
  319. f.print("FILEREC"); f.print('='); f.print((*c).logFileRec); f.print('\n');
  320. f.print("FILENO"); f.print('='); f.print((*c).logFileNo); f.print('\n');
  321. f.print("FILENUM"); f.print('='); f.print((*c).logFileNum); f.print('\n');
  322. f.print("DELAY"); f.print('='); f.print((*c).txDelay); f.print('\n');
  323. f.print("TRUSTED"); f.print('='); f.print((*c).trusted); f.print('\n');
  324. f.print("EXPERT"); f.print('='); f.print((*c).expert); f.print('\n');
  325. f.print("SEEN"); f.print('='); f.print((*c).seen); f.print('\n');
  326. f.print("MONITOR"); f.print('='); f.print((*c).monitor); f.print('\n');
  327. f.close();
  328. return(1);
  329. }
  330. // ----------------------------------------------------------------------------
  331. // Add a line with statistics to the log.
  332. //
  333. // We put the check in the function to protect against calling
  334. // the function without STAT_LOG being proper defined
  335. // ToDo: Store the fileNo and the fileRec in the status file to save for
  336. // restarts
  337. //
  338. // Parameters:
  339. // line; char array with characters to write to log
  340. // cnt;
  341. // Returns:
  342. // <none>
  343. // ----------------------------------------------------------------------------
  344. int addLog(const unsigned char * line, int cnt)
  345. {
  346. #if STAT_LOG==1
  347. char fn[16];
  348. if (gwayConfig.logFileRec > LOGFILEREC) { // Have to make define for this
  349. gwayConfig.logFileRec = 0; // In new logFile start with record 0
  350. gwayConfig.logFileNo++; // Increase file ID
  351. gwayConfig.logFileNum++; // Increase number of log files
  352. }
  353. gwayConfig.logFileRec++;
  354. // If we have too many logfies, delete the oldest
  355. //
  356. if (gwayConfig.logFileNum > LOGFILEMAX){
  357. sprintf(fn,"/log-%d", gwayConfig.logFileNo - LOGFILEMAX);
  358. #if _DUSB>=1
  359. if (( debug>=0 ) && ( pdebug & P_GUI )) {
  360. Serial.print(F("G addLog:: Too many logfile, deleting="));
  361. Serial.println(fn);
  362. }
  363. #endif //_DUSB
  364. SPIFFS.remove(fn);
  365. gwayConfig.logFileNum--;
  366. }
  367. // Make sure we have the right fileno
  368. sprintf(fn,"/log-%d", gwayConfig.logFileNo);
  369. // If there is no SPIFFS, Error
  370. // Make sure to write the config record/line also
  371. if (!SPIFFS.exists(fn)) {
  372. #if _DUSB>=1
  373. if (( debug >= 1 ) && ( pdebug & P_GUI )) {
  374. Serial.print(F("G ERROR:: addLog:: file="));
  375. Serial.print(fn);
  376. Serial.print(F(" does not exist .. rec="));
  377. Serial.print(gwayConfig.logFileRec);
  378. Serial.println();
  379. }
  380. #endif //_DUSB
  381. }
  382. File f = SPIFFS.open(fn, "a");
  383. if (!f) {
  384. #if _DUSB>=1
  385. if (( debug>=1 ) && ( pdebug & P_GUI )) {
  386. Serial.println("G file open failed=");
  387. Serial.println(fn);
  388. }
  389. #endif //_DUSB
  390. return(0); // If file open failed, return
  391. }
  392. int i;
  393. #if _DUSB>=1
  394. if (( debug>=1 ) && ( pdebug & P_GUI )) {
  395. Serial.print(F("G addLog:: fileno="));
  396. Serial.print(gwayConfig.logFileNo);
  397. Serial.print(F(", rec="));
  398. Serial.print(gwayConfig.logFileRec);
  399. Serial.print(F(": "));
  400. #if _DUSB>=2
  401. for (i=0; i< 12; i++) { // The first 12 bytes contain non printable characters
  402. Serial.print(line[i],HEX);
  403. Serial.print(' ');
  404. }
  405. #else
  406. i+=12;
  407. #endif //_DUSB>=2
  408. Serial.print((char *) &line[i]); // The rest if the buffer contains ascii
  409. Serial.println();
  410. }
  411. #endif //_DUSB
  412. for (i=0; i< 12; i++) { // The first 12 bytes contain non printable characters
  413. // f.print(line[i],HEX);
  414. f.print('*');
  415. }
  416. f.write(&(line[i]), cnt-12); // write/append the line to the file
  417. f.print('\n');
  418. f.close(); // Close the file after appending to it
  419. #endif //STAT_LOG
  420. return(1);
  421. }
  422. // ----------------------------------------------------------------------------
  423. // Print (all) logfiles
  424. //
  425. // ----------------------------------------------------------------------------
  426. void printLog()
  427. {
  428. char fn[16];
  429. int i=0;
  430. #if _DUSB>=1
  431. while (i< LOGFILEMAX ) {
  432. sprintf(fn,"/log-%d", gwayConfig.logFileNo - i);
  433. if (!SPIFFS.exists(fn)) break; // break the loop
  434. // Open the file for reading
  435. File f = SPIFFS.open(fn, "r");
  436. int j;
  437. for (j=0; j<LOGFILEREC; j++) {
  438. String s=f.readStringUntil('\n');
  439. if (s.length() == 0) break;
  440. Serial.println(s.substring(12)); // Skip the first 12 Gateway specific binary characters
  441. yield();
  442. }
  443. i++;
  444. }
  445. #endif //_DUSB
  446. } //printLog
  447. #if _SEENMAX>=1
  448. // ----------------------------------------------------------------------------
  449. // initSeen
  450. // Init the lisrScreen array
  451. // ----------------------------------------------------------------------------
  452. int initSeen(struct nodeSeen *listSeen) {
  453. int i;
  454. for (i=0; i< _SEENMAX; i++) {
  455. listSeen[i].idSeen=0;
  456. listSeen[i].sfSeen=0;
  457. listSeen[i].cntSeen=0;
  458. listSeen[i].chnSeen=0;
  459. listSeen[i].timSeen=0;
  460. }
  461. return(1);
  462. }
  463. // ----------------------------------------------------------------------------
  464. // readSeen
  465. // This function read the stored information from writeSeen.
  466. //
  467. // Parameters:
  468. // Return:
  469. // ----------------------------------------------------------------------------
  470. int readSeen(const char *fn, struct nodeSeen *listSeen) {
  471. int i;
  472. if (!SPIFFS.exists(fn)) {
  473. #if _DUSB>=1
  474. Serial.print("WARNING:: readSeen, history file not exists ");
  475. #endif //_DUSB
  476. initSeen(listSeen); // XXX make all initial declarations here if config vars need to have a value
  477. Serial.println(fn);
  478. return(-1);
  479. }
  480. File f = SPIFFS.open(fn, "r");
  481. if (!f) {
  482. #if _DUSB>=1
  483. Serial.print("readConfig:: ERROR open file=");
  484. Serial.print(fn);
  485. Serial.println();
  486. #endif //_DUSB
  487. return(-1);
  488. }
  489. for (i=0; i<_SEENMAX; i++) {
  490. String val;
  491. if (!f.available()) {
  492. #if _DUSB>=1
  493. Serial.println(F("readSeen:: No more info left in file"));
  494. #endif //_DUSB
  495. }
  496. val=f.readStringUntil('\t'); listSeen[i].timSeen = (uint32_t) val.toInt();
  497. val=f.readStringUntil('\t'); listSeen[i].idSeen = (uint32_t) val.toInt();
  498. val=f.readStringUntil('\t'); listSeen[i].cntSeen = (uint32_t) val.toInt();
  499. val=f.readStringUntil('\t'); listSeen[i].chnSeen = (uint8_t) val.toInt();
  500. val=f.readStringUntil('\n'); listSeen[i].sfSeen = (uint8_t) val.toInt();
  501. }
  502. f.close();
  503. #if _DUSB>=1
  504. printSeen(listSeen);
  505. #endif //_DUSB
  506. }
  507. // ----------------------------------------------------------------------------
  508. // writeSeen
  509. // Once every few messages, update the SPIFFS file and write the array.
  510. // Parameters:
  511. // - fn contains the filename to write
  512. // - listSeen contains the _SEENMAX array of list structures
  513. // Return values:
  514. // - return 1 on success
  515. // ----------------------------------------------------------------------------
  516. int writeSeen(const char *fn, struct nodeSeen *listSeen) {
  517. int i;
  518. if (!SPIFFS.exists(fn)) {
  519. #if _DUSB>=1
  520. Serial.print("WARNING:: writeSeen, file not exists, formatting ");
  521. #endif //_DUSB
  522. initSeen(listSeen); // XXX make all initial declarations here if config vars need to have a value
  523. #if _DUSB>=1
  524. Serial.println(fn);
  525. #endif //_DUSB
  526. }
  527. File f = SPIFFS.open(fn, "w");
  528. if (!f) {
  529. #if _DUSB>=1
  530. Serial.print("writeConfig:: ERROR open file=");
  531. Serial.print(fn);
  532. Serial.println();
  533. #endif //_DUSB
  534. return(-1);
  535. }
  536. for (i=0; i<_SEENMAX; i++) {
  537. unsigned long timSeen;
  538. f.print(listSeen[i].timSeen); f.print('\t');
  539. // Typecast to long to avoid errors in unsigned conversion!
  540. f.print((long) listSeen[i].idSeen); f.print('\t');
  541. f.print(listSeen[i].cntSeen); f.print('\t');
  542. f.print(listSeen[i].chnSeen); f.print('\t');
  543. f.print(listSeen[i].sfSeen); f.print('\n');
  544. //f.print(listSeen[i].rssiSeen); f.print('\t');
  545. //f.print(listSeen[i].datSeen); f.print('\n');
  546. }
  547. f.close();
  548. return(1);
  549. }
  550. // ----------------------------------------------------------------------------
  551. // printSeen
  552. // - This function writes the last seen array to the USB
  553. // ----------------------------------------------------------------------------
  554. int printSeen(struct nodeSeen *listSeen) {
  555. int i;
  556. #if _DUSB>=1
  557. if (( debug>=2 ) && ( pdebug & P_MAIN )) {
  558. Serial.println(F("printSeen:: "));
  559. for (i=0; i<_SEENMAX; i++) {
  560. if (listSeen[i].idSeen != 0) {
  561. String response;
  562. Serial.print(i);
  563. Serial.print(F(", TM="));
  564. stringTime(listSeen[i].timSeen, response);
  565. Serial.print(response);
  566. Serial.print(F(", addr=0x"));
  567. Serial.print(listSeen[i].idSeen,HEX);
  568. Serial.print(F(", SF=0x"));
  569. Serial.print(listSeen[i].sfSeen,HEX);
  570. Serial.println();
  571. }
  572. }
  573. }
  574. #endif //_DUSB
  575. return(1);
  576. }
  577. // ----------------------------------------------------------------------------
  578. // addSeen
  579. // With every new message received:
  580. // - Look whether the message is already in the array, if so update existing
  581. // message. If not, create new record.
  582. // - With this record, update the SF settings
  583. // ----------------------------------------------------------------------------
  584. int addSeen(struct nodeSeen *listSeen, struct stat_t stat) {
  585. int i;
  586. // ( message[4]<<24 | message[3]<<16 | message[2]<<8 | message[1] )
  587. for (i=0; i< _SEENMAX; i++) {
  588. if ((listSeen[i].idSeen==stat.node) ||
  589. (listSeen[i].idSeen==0))
  590. {
  591. #if _DUSB>=2
  592. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  593. Serial.print(F("addSeen:: index="));
  594. Serial.print(i);
  595. }
  596. #endif //_DUSB
  597. listSeen[i].idSeen = stat.node;
  598. listSeen[i].chnSeen = stat.ch;
  599. listSeen[i].sfSeen |= stat.sf; // Or the argument
  600. listSeen[i].timSeen = stat.tmst;
  601. listSeen[i].cntSeen++; // Not included on functiin paras
  602. writeSeen(_SEENFILE, listSeen);
  603. break;
  604. }
  605. }
  606. if (i>=_SEENMAX) {
  607. #if _DUSB>=1
  608. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  609. Serial.print(F("addSeen:: exit=0, index="));
  610. Serial.println(i);
  611. }
  612. #endif //_DUSB
  613. return(0);
  614. }
  615. return(1);
  616. }
  617. // ----------------------------------------------------------------------------
  618. // listDir
  619. // List the directory and put it in
  620. // ----------------------------------------------------------------------------
  621. void listDir(char * dir)
  622. {
  623. #if _DUSB>=1
  624. // Nothing here
  625. #endif //_DUSB
  626. }
  627. #endif //_SEENMAX>0 End of File